summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/auth/components/LoginDesktop.jsx5
-rw-r--r--src/lib/auth/components/LoginMobile.jsx4
-rw-r--r--src/lib/auth/hooks/useLogin.js2
-rw-r--r--src/lib/checkout/api/checkoutApi.js34
-rw-r--r--src/lib/checkout/api/getVoucher.js37
-rw-r--r--src/lib/checkout/components/Checkout.jsx236
-rw-r--r--src/lib/checkout/components/CheckoutOld.jsx2
-rw-r--r--src/lib/checkout/components/CheckoutSection.jsx2
-rw-r--r--src/lib/home/components/PreferredBrand.jsx38
-rw-r--r--src/lib/home/components/PromotionProgram.jsx65
-rw-r--r--src/lib/product/components/ProductCard.jsx61
-rw-r--r--src/lib/product/components/ProductFilterDesktop.jsx10
-rw-r--r--src/lib/product/components/ProductFilterDesktopPromotion.jsx132
-rw-r--r--src/lib/product/components/ProductSearch.jsx2
-rw-r--r--src/lib/promo/components/Promocrumb.jsx40
-rw-r--r--src/lib/transaction/components/Transaction.jsx171
-rw-r--r--src/lib/transaction/components/Transactions.jsx10
-rw-r--r--src/lib/variant/components/VariantCard.jsx36
18 files changed, 744 insertions, 143 deletions
diff --git a/src/lib/auth/components/LoginDesktop.jsx b/src/lib/auth/components/LoginDesktop.jsx
index 1333db14..9a68dc53 100644
--- a/src/lib/auth/components/LoginDesktop.jsx
+++ b/src/lib/auth/components/LoginDesktop.jsx
@@ -8,6 +8,7 @@ import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner';
+import Image from 'next/image';
const LoginDesktop = () => {
const {
@@ -108,7 +109,7 @@ const LoginDesktop = () => {
{!isLoading ? 'Masuk' : 'Loading...'}
</button>
</form>
- {/* <div className='flex items-center mt-3 mb-3'>
+ <div className='flex items-center mt-3 mb-3'>
<hr className='flex-1' />
<p className='text-gray-400'>ATAU</p>
<hr className='flex-1' />
@@ -127,7 +128,7 @@ const LoginDesktop = () => {
height={10}
/>
<p>Masuk dengan Google</p>
- </button> */}
+ </button>
<div className='text-gray_r-11 mt-10'>
Belum punya akun Indoteknik?{' '}
diff --git a/src/lib/auth/components/LoginMobile.jsx b/src/lib/auth/components/LoginMobile.jsx
index 40924fbe..d2bf704f 100644
--- a/src/lib/auth/components/LoginMobile.jsx
+++ b/src/lib/auth/components/LoginMobile.jsx
@@ -117,7 +117,7 @@ const LoginMobile = () => {
{!isLoading ? 'Masuk' : 'Loading...'}
</button>
</form>
- {/* <div className='flex items-center mt-3 mb-3'>
+ <div className='flex items-center mt-3 mb-3'>
<hr className='flex-1' />
<p className='text-gray-400'>ATAU</p>
<hr className='flex-1' />
@@ -136,7 +136,7 @@ const LoginMobile = () => {
height={10}
/>
<p>Masuk dengan Google</p>
- </button> */}
+ </button>
<div className='text-gray_r-11 mt-4'>
Belum punya akun Indoteknik?{' '}
diff --git a/src/lib/auth/hooks/useLogin.js b/src/lib/auth/hooks/useLogin.js
index dc9580ea..dd5a4b03 100644
--- a/src/lib/auth/hooks/useLogin.js
+++ b/src/lib/auth/hooks/useLogin.js
@@ -74,7 +74,7 @@ const useLogin = () => {
if (data.isAuth) {
session.odooUser = data.user;
setCookie('auth', JSON.stringify(session?.odooUser));
- router.push(decodeURIComponent(router?.query?.next) ?? '/');
+ router.push(router?.query?.next || '/');
return;
}
};
diff --git a/src/lib/checkout/api/checkoutApi.js b/src/lib/checkout/api/checkoutApi.js
index 24f1868a..fd982fff 100644
--- a/src/lib/checkout/api/checkoutApi.js
+++ b/src/lib/checkout/api/checkoutApi.js
@@ -1,28 +1,20 @@
-import odooApi from '@/core/api/odooApi'
-import { getAuth } from '@/core/utils/auth'
+import odooApi from '@/core/api/odooApi';
+import { getAuth } from '@/core/utils/auth';
export const checkoutApi = async ({ data }) => {
- const auth = getAuth()
+ const auth = getAuth();
const dataCheckout = await odooApi(
'POST',
`/api/v1/partner/${auth.partnerId}/sale_order/checkout`,
data
- )
- return dataCheckout
-}
+ );
+ return dataCheckout;
+};
-export const getProductsCheckout = async (voucher, query) => {
- const id = getAuth()?.id
- let products
- if(voucher && query){
- products = await odooApi('GET',`/api/v1/user/${id}/sale_order/checkout?voucher=${voucher}&source=buy`)
- }else if (voucher){
- products = await odooApi('GET',`/api/v1/user/${id}/sale_order/checkout?voucher=${voucher}`)
- }else if (query) {
- products = await odooApi('GET',`/api/v1/user/${id}/sale_order/checkout?source=buy`)
- }else{
- products = await odooApi('GET',`/api/v1/user/${id}/sale_order/checkout`)
- }
-
- return products
-}
+export const getProductsCheckout = async (query) => {
+ const queryParam = new URLSearchParams(query);
+ const userId = getAuth()?.id;
+ const url = `/api/v1/user/${userId}/sale_order/checkout?${queryParam.toString()}`;
+ const result = await odooApi('GET', url);
+ return result;
+};
diff --git a/src/lib/checkout/api/getVoucher.js b/src/lib/checkout/api/getVoucher.js
index 07cf376e..54c8cce5 100644
--- a/src/lib/checkout/api/getVoucher.js
+++ b/src/lib/checkout/api/getVoucher.js
@@ -1,21 +1,24 @@
-import odooApi from '@/core/api/odooApi'
+import odooApi from '@/core/api/odooApi';
-export const getVoucher = async (id, source) => {
- let dataVoucher = null
- if(source){
- dataVoucher = await odooApi('GET', `/api/v1/user/${id}/voucher?source=${source}`)
- }else {
- dataVoucher = await odooApi('GET', `/api/v1/user/${id}/voucher`)
- }
- return dataVoucher
-}
+export const getVoucher = async (id, query) => {
+ const queryParam = new URLSearchParams(query);
+ const url = `/api/v1/user/${id}/voucher?${queryParam.toString()}`;
+ const dataVoucher = await odooApi('GET', url);
+ return dataVoucher;
+};
export const findVoucher = async (code, id, source) => {
- let dataVoucher = null
- if(source){
- dataVoucher = await odooApi('GET', `/api/v1/user/${id}/voucher?code=${code}&source=${source}`)
- }else{
- dataVoucher = await odooApi('GET', `/api/v1/user/${id}/voucher?code=${code}`)
+ let dataVoucher = null;
+ if (source) {
+ dataVoucher = await odooApi(
+ 'GET',
+ `/api/v1/user/${id}/voucher?code=${code}&source=${source}`
+ );
+ } else {
+ dataVoucher = await odooApi(
+ 'GET',
+ `/api/v1/user/${id}/voucher?code=${code}`
+ );
}
- return dataVoucher
-}
+ return dataVoucher;
+};
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 7a456d70..f640299a 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -43,9 +43,16 @@ const Checkout = () => {
const auth = useAuth();
const [activeVoucher, SetActiveVoucher] = useState(null);
-
- const { data: cartCheckout } = useQuery('cartCheckout-' + activeVoucher, () =>
- getProductsCheckout(activeVoucher, query)
+ const [activeVoucherShipping, setActiveVoucherShipping] = useState(null);
+
+ const { data: cartCheckout } = useQuery(
+ ['cartCheckout', activeVoucher, activeVoucherShipping],
+ () =>
+ getProductsCheckout({
+ source: query,
+ voucher: activeVoucher,
+ voucher_shipping: activeVoucherShipping,
+ })
);
const [selectedAddress, setSelectedAddress] = useState({
@@ -103,6 +110,7 @@ const Checkout = () => {
const [bottomPopupTnC, SetBottomPopupTnC] = useState(null);
const [itemTnC, setItemTnC] = useState(null);
const [listVouchers, SetListVoucher] = useState(null);
+ const [listVoucherShippings, SetListVoucherShipping] = useState(null);
const [discountVoucher, SetDiscountVoucher] = useState(0);
const [codeVoucher, SetCodeVoucher] = useState(null);
const [findCodeVoucher, SetFindVoucher] = useState(null);
@@ -112,19 +120,30 @@ const Checkout = () => {
const [loadingVoucher, setLoadingVoucher] = useState(true);
const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false);
const [grandTotal, setGrandTotal] = useState(0);
+ const [hasFlashSale, setHasFlashSale] = useState(false);
const expedisiValidation = useRef(null);
const voucher = async () => {
if (!listVouchers) {
try {
- let dataVoucher = await getVoucher(auth?.id, query);
+ setLoadingVoucher(true);
+ let dataVoucher = await getVoucher(auth?.id, {
+ source: query,
+ });
SetListVoucher(dataVoucher);
+
+ let dataVoucherShipping = await getVoucher(auth?.id, {
+ source: query,
+ type: 'shipping',
+ });
+ SetListVoucherShipping(dataVoucherShipping);
} finally {
setLoadingVoucher(false);
}
}
};
+
const VoucherCode = async (code) => {
let dataVoucher = await findVoucher(code, auth.id, query);
if (dataVoucher.length <= 0) {
@@ -224,7 +243,10 @@ const Checkout = () => {
setProducts(cartCheckout?.products);
setCheckWeight(cartCheckout?.hasProductWithoutWeight);
setTotalWeight(cartCheckout?.totalWeight.g);
+ const hasFlashSale = cartCheckout?.products.some(product => product.hasFlashsale);
+ setHasFlashSale(hasFlashSale);
}, [cartCheckout]);
+
useEffect(() => {
setCheckoutValidation(false);
@@ -299,7 +321,7 @@ const Checkout = () => {
useEffect(() => {
const GT =
cartCheckout?.grandTotal +
- Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000;
+ Math.round(parseInt(finalShippingAmt * 1.1) / 1000) * 1000;
const finalGT = GT < 0 ? 0 : GT;
setGrandTotal(finalGT);
}, [biayaKirim, cartCheckout?.grandTotal, activeVoucher]);
@@ -333,15 +355,19 @@ const Checkout = () => {
quantity: product.quantity,
}));
let data = {
- partner_shipping_id: auth.partnerId,
- partner_invoice_id: auth.partnerId,
+ // partner_shipping_id: auth.partnerId,
+ // partner_invoice_id: auth.partnerId,
+ partner_shipping_id: selectedAddress?.shipping?.id || auth.partnerId,
+ partner_invoice_id: selectedAddress?.invoicing?.id || auth.partnerId,
user_id: auth.id,
order_line: JSON.stringify(productOrder),
delivery_amount: biayaKirim,
carrier_id: selectedCarrierId,
estimated_arrival_days: splitDuration(etd),
delivery_service_type: selectedExpedisiService,
+ flash_sale : hasFlashSale, // dibuat negasi untuk ngetest kebalikan nilai false
voucher: activeVoucher,
+ voucher_shipping: activeVoucherShipping,
type: 'sale_order',
};
@@ -356,7 +382,7 @@ const Checkout = () => {
toast.error('Gagal melakukan transaksi, terjadi kesalahan internal');
return;
}
-
+
gtagPurchase(products, biayaKirim, isCheckouted.name);
const midtrans = async () => {
@@ -437,6 +463,11 @@ const Checkout = () => {
return false;
}, [products]);
+ const voucherShippingAmt = cartCheckout?.discountVoucherShipping || 0;
+ const discShippingAmt = Math.min(biayaKirim, voucherShippingAmt);
+
+ const finalShippingAmt = biayaKirim - discShippingAmt;
+
return (
<>
<BottomPopup
@@ -546,8 +577,145 @@ const Checkout = () => {
</div>
)}
- <hr className='mt-10 my-4 border-gray_r-10' />
- <div className=''>
+ <hr className='mt-8 mb-4 border-gray_r-8' />
+
+ {listVoucherShippings && listVoucherShippings?.length > 0 && (
+ <div>
+ <h3 className='font-semibold mb-4'>Promo Gratis Ongkir</h3>
+ {listVoucherShippings?.map((item) => (
+ <div key={item.id} className='relative'>
+ <div
+ className={`border border-solid mb-5 w-full hover:cursor-pointer p-2 pl-4 pr-4 `}
+ >
+ {item.canApply && (
+ <div
+ class='p-2 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:text-green-400'
+ role='alert'
+ >
+ <p>
+ Potensi potongan sebesar{' '}
+ <span className='text-green font-bold'>
+ {currencyFormat(item.discountVoucher)}
+ </span>
+ </p>
+ </div>
+ )}
+ {!item.canApply && (
+ <div
+ class='p-2 mb-4 text-sm text-red-800 rounded-lg bg-red-50'
+ role='alert'
+ onClick={() => handlingTnC(item)}
+ >
+ <p>
+ Voucher tidak bisa di gunakan,{' '}
+ <span className='text-red font-bold'>
+ Baca Selengkapnya !
+ </span>
+ </p>
+ </div>
+ )}
+
+ <div className={`flex gap-x-3 relative`}>
+ {item.canApply === false && (
+ <div className='absolute w-full h-full bg-gray_r-3/40 top-0 left-0 z-50' />
+ )}
+ <div className='hidden md:w-[250px] md:block'>
+ <Image
+ src={item.image}
+ alt={item.name}
+ className={`object-cover`}
+ />
+ </div>
+ <div className='w-full'>
+ <div className='flex justify-between gap-x-2 mb-1 items-center'>
+ <div className=''>
+ <h3 className='font-semibold'>{item.name}</h3>
+ <div className='mt-1'>
+ <span className='text-sm line-clamp-3'>
+ {item.description}{' '}
+ </span>
+ </div>
+ </div>
+ <div className='flex justify-end'>
+ <label class='relative inline-flex items-center cursor-pointer'>
+ <input
+ type='checkbox'
+ value=''
+ class='sr-only peer'
+ checked={activeVoucherShipping === item.code}
+ onChange={() =>
+ setActiveVoucherShipping(
+ activeVoucherShipping === item.code
+ ? null
+ : item.code
+ )
+ }
+ />
+ <div class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-green-300 dark:peer-focus:ring-green-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-green-600"></div>
+ </label>
+ </div>
+ </div>
+ <hr className='mt-2 my-2 border-gray_r-8' />
+ <div className='flex justify-between items-center'>
+ <p className='text-justify text-sm md:text-xs'>
+ Kode Voucher :{' '}
+ <span className='text-red-500 font-semibold'>
+ {item.code}
+ </span>
+ </p>
+ <p className='text-sm md:text-xs'>
+ {activeVoucher === item.code && (
+ <span className=' text-green-600'>
+ Voucher digunakan{' '}
+ </span>
+ )}
+ </p>
+ </div>
+ <div className='flex items-center mt-3'>
+ <svg
+ aria-hidden='true'
+ fill='none'
+ stroke='currentColor'
+ stroke-width='1.5'
+ viewBox='0 0 24 24'
+ className='w-5 text-black'
+ >
+ <path
+ d='M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z'
+ stroke-linecap='round'
+ stroke-linejoin='round'
+ ></path>
+ </svg>
+ <div className='flex justify-between items-center'>
+ <div className='text-left ml-3 text-sm '>
+ Berakhir dalam{' '}
+ <span className='text-red-600'>
+ {item.remainingTime}
+ </span>{' '}
+ lagi,{' '}
+ </div>
+ <div
+ className='text-sm ml-2 text-red-600'
+ onClick={() => handlingTnC(item)}
+ >
+ Baca S&K
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div className='mt-3'>
+ <p className='text-justify text-sm '></p>
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ )}
+
+ <hr className='mt-8 mb-4 border-gray_r-8' />
+
+ <div>
{!loadingVoucher && listVouchers?.length === 0 ? (
<div className='flex items-center justify-center mt-4 mb-4'>
<div className='text-center'>
@@ -732,14 +900,7 @@ const Checkout = () => {
</div>
</div>
<div className='mt-3'>
- <p className='text-justify text-sm '>
- {/* {item.canApply === false
- ? 'Tambah ' +
- currencyFormat(item.differenceToApply) +
- ' untuk pakai promo ini'
- : 'Potensi potongan sebesar ' +
- currencyFormat(hitungDiscountVoucher(item.code))} */}
- </p>
+ <p className='text-justify text-sm '></p>
</div>
</div>
</div>
@@ -905,14 +1066,18 @@ const Checkout = () => {
</div>
<div className='flex gap-x-2 justify-between'>
<div className='text-gray_r-11'>
- Biaya Kirim <p className='text-xs mt-3'>{etdFix}</p>
- </div>
- <div>
- {currencyFormat(
- Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000
- )}
+ Biaya Kirim <p className='text-xs mt-1'>{etdFix}</p>
</div>
+ <div>{currencyFormat(biayaKirim)}</div>
</div>
+ {activeVoucherShipping && voucherShippingAmt && (
+ <div className='flex gap-x-2 justify-between'>
+ <div className='text-gray_r-11'>Diskon Kirim</div>
+ <div className='text-danger-500'>
+ - {currencyFormat(discShippingAmt)}
+ </div>
+ </div>
+ )}
</div>
)}
@@ -941,7 +1106,7 @@ const Checkout = () => {
<div className='mt-4 mb-4'>
<button
type='button'
- onClick={() => {
+ onClick={async () => {
SetBottomPopup(true);
voucher();
}}
@@ -1197,14 +1362,18 @@ const Checkout = () => {
<div className='flex gap-x-2 justify-between'>
<div className='text-gray_r-11'>
Biaya Kirim
- <p className='text-xs mt-3'>{etdFix}</p>
- </div>
- <div>
- {currencyFormat(
- Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000
- )}
+ <p className='text-xs mt-1'>{etdFix}</p>
</div>
+ <div>{currencyFormat(biayaKirim)}</div>
</div>
+ {activeVoucherShipping && voucherShippingAmt && (
+ <div className='flex gap-x-2 justify-between'>
+ <div className='text-gray_r-11'>Diskon Kirim</div>
+ <div className='text-danger-500'>
+ - {currencyFormat(discShippingAmt)}
+ </div>
+ </div>
+ )}
</div>
)}
@@ -1224,6 +1393,9 @@ const Checkout = () => {
<div>Grand Total</div>
<div className='font-semibold text-gray_r-12'>
{currencyFormat(grandTotal)}
+ {currencyFormat(
+ cartCheckout?.grandTotal + finalShippingAmt
+ )}
</div>
</div>
)}
@@ -1454,7 +1626,7 @@ const SectionExpedisi = ({
dengan menghubungi admin melalui{' '}
<a
className='text-danger-500 inline'
- href='https://api.whatsapp.com/send?phone=628128080622'
+ href='https://api.whatsapp.com/send?phone=6281717181922'
>
tautan ini
</a>
diff --git a/src/lib/checkout/components/CheckoutOld.jsx b/src/lib/checkout/components/CheckoutOld.jsx
index d57fbd66..e2c45ce6 100644
--- a/src/lib/checkout/components/CheckoutOld.jsx
+++ b/src/lib/checkout/components/CheckoutOld.jsx
@@ -696,7 +696,7 @@ const SectionExpedisi = ({ address, listExpedisi, setSelectedExpedisi, checkWeig
diatur beratnya. Mohon atur berat barang dengan menghubungi admin melalui{' '}
<a
className='text-danger-500 inline'
- href='https://api.whatsapp.com/send?phone=628128080622'
+ href='https://api.whatsapp.com/send?phone=6281717181922'
>
tautan ini
</a>
diff --git a/src/lib/checkout/components/CheckoutSection.jsx b/src/lib/checkout/components/CheckoutSection.jsx
index 7f9ea08a..affe6138 100644
--- a/src/lib/checkout/components/CheckoutSection.jsx
+++ b/src/lib/checkout/components/CheckoutSection.jsx
@@ -120,7 +120,7 @@ export const SectionExpedisi = ({
dengan menghubungi admin melalui{' '}
<a
className='text-danger-500 inline'
- href='https://api.whatsapp.com/send?phone=628128080622'
+ href='https://api.whatsapp.com/send?phone=6281717181922'
>
tautan ini
</a>
diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx
index 571c4745..ec09aa4e 100644
--- a/src/lib/home/components/PreferredBrand.jsx
+++ b/src/lib/home/components/PreferredBrand.jsx
@@ -1,13 +1,41 @@
import { Swiper, SwiperSlide } from 'swiper/react'
+import { useCallback, useEffect, useState } from 'react'
import usePreferredBrand from '../hooks/usePreferredBrand'
import PreferredBrandSkeleton from './Skeleton/PreferredBrandSkeleton'
import BrandCard from '@/lib/brand/components/BrandCard'
import useDevice from '@/core/hooks/useDevice'
import Link from '@/core/components/elements/Link/Link'
+import axios from 'axios'
const PreferredBrand = () => {
let query = 'level_s'
let params = 'prioritas'
+ const [isLoading, setIsLoading] = useState(true)
+ const [startWith, setStartWith] = useState(null)
+ const [manufactures, setManufactures] = useState([])
+
+ const loadBrand = useCallback(async () => {
+ setIsLoading(true)
+ const name = startWith ? `${startWith}*` : ''
+ const result = await axios(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=${name}`)
+
+ setIsLoading(false)
+ setManufactures((manufactures) => [...result.data])
+ }, [startWith])
+
+ const toggleStartWith = (alphabet) => {
+ setManufactures([])
+ if (alphabet == startWith) {
+ setStartWith(null)
+ return
+ }
+ setStartWith(alphabet)
+ }
+
+ useEffect(() => {
+ loadBrand()
+ }, [loadBrand])
+
const { preferredBrands } = usePreferredBrand(query)
const { isMobile, isDesktop } = useDevice()
@@ -21,12 +49,12 @@ const PreferredBrand = () => {
</Link>
)}
</div>
- {preferredBrands.isLoading && <PreferredBrandSkeleton />}
- {!preferredBrands.isLoading && (
+ {manufactures.isLoading && <PreferredBrandSkeleton />}
+ {!manufactures.isLoading && (
<Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 24} freeMode>
- {preferredBrands.data?.data.map((brand) => (
- <SwiperSlide key={brand.id}>
- <BrandCard brand={brand} />
+ {manufactures.map((manufacture) => (
+ <SwiperSlide key={manufacture.id}>
+ <BrandCard brand={manufacture} />
</SwiperSlide>
))}
</Swiper>
diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx
new file mode 100644
index 00000000..5034fd28
--- /dev/null
+++ b/src/lib/home/components/PromotionProgram.jsx
@@ -0,0 +1,65 @@
+import Link from '@/core/components/elements/Link/Link'
+import Image from 'next/image'
+import { bannerApi } from '@/api/bannerApi';
+import useDevice from '@/core/hooks/useDevice'
+import { Swiper, SwiperSlide } from 'swiper/react';
+const { useQuery } = require('react-query')
+const BannerSection = () => {
+ const promotionProgram = useQuery('promotionProgram', bannerApi({ type: 'banner-promotion' }));
+ const { isMobile, isDesktop } = useDevice()
+
+ return (
+ <div className='px-4 sm:px-0'>
+ <div className='flex justify-between items-center mb-4 '>
+ <div className='font-semibold sm:text-h-lg'>Promo Tersedia</div>
+ {isDesktop && (
+ <Link href='/shop/promo' className='!text-red-500 font-semibold'>
+ Lihat Semua
+ </Link>
+ )}
+ </div>
+ {isDesktop && (promotionProgram.data &&
+ promotionProgram.data?.length > 0 && (
+ <div className='grid grid-cols-3 sm:grid-cols-3 gap-4 rounded-md'>
+ {promotionProgram.data?.map((banner) => (
+ <Link key={banner.id} href={banner.url}>
+ <Image
+ width={439}
+ height={150}
+ quality={100}
+ src={banner.image}
+ alt={banner.name}
+ className='h-auto w-full rounded hover:scale-105 transition duration-500 ease-in-out'
+ />
+ </Link>
+ ))}
+ </div>
+
+ ))}
+
+{isMobile && (
+
+ <Swiper slidesPerView={1.1} spaceBetween={8} freeMode>
+ {promotionProgram.data?.map((banner) => (
+ <SwiperSlide key={banner.id}>
+ <Link key={banner.id} href={banner.url}>
+ <Image
+ width={439}
+ height={150}
+ quality={100}
+ src={banner.image}
+ alt={banner.name}
+ className='h-auto w-full rounded '
+ />
+ </Link>
+ </SwiperSlide>
+ ))}
+ </Swiper>
+
+ )}
+ </div>
+
+ )
+}
+
+export default BannerSection
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx
index 38ed35f8..98732407 100644
--- a/src/lib/product/components/ProductCard.jsx
+++ b/src/lib/product/components/ProductCard.jsx
@@ -1,7 +1,7 @@
import clsx from 'clsx';
import ImageNext from 'next/image';
import { useRouter } from 'next/router';
-import { useMemo } from 'react';
+import { useMemo, useEffect, useState } from 'react';
import Image from '@/core/components/elements/Image/Image';
import Link from '@/core/components/elements/Link/Link';
@@ -15,6 +15,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
const router = useRouter();
const utmSource = useUtmSource();
+
const callForPriceWhatsapp = whatsappUrl('product', {
name: product.name,
manufacture: product.manufacture?.name,
@@ -41,11 +42,39 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
return (
<div className='rounded shadow-sm border border-gray_r-4 bg-white h-[300px] md:h-[350px]'>
<Link href={URL.product} className='border-b border-gray_r-4 relative'>
+ <div className="relative">
<Image
src={image}
alt={product?.name}
- className='w-full object-contain object-center h-36 sm:h-48'
+ className="gambarA w-full object-contain object-center h-36 sm:h-48"
/>
+ <div className="absolute top-0 right-0 flex mt-3">
+ <div className="gambarB ">
+ {product?.isSni && (
+ <ImageNext
+ src="/images/sni-logo.png"
+ alt="SNI Logo"
+ className="w-4 h-5 object-contain object-top sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ <div className="gambarC ">
+ {product?.isTkdn && (
+ <ImageNext
+ src="/images/TKDN.png"
+ alt="TKDN"
+ className="w-11 h-6 object-contain object-top ml-1 mr-1 sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ </div>
+ </div>
+
+
{router.pathname != '/' && product?.flashSale?.id > 0 && (
<div className='absolute bottom-0 w-full grid'>
<div className='absolute bottom-0 w-full h-full'>
@@ -171,11 +200,37 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
<div className='flex bg-white'>
<div className='w-4/12'>
<Link href={URL.product} className='relative'>
+ <div className="relative">
<Image
src={image}
alt={product?.name}
- className='w-full object-contain object-center h-36'
+ className="gambarA w-full object-contain object-center h-36 sm:h-48"
/>
+ <div className="absolute top-0 right-0 flex mt-3">
+ <div className="gambarB ">
+ {product?.isSni && (
+ <ImageNext
+ src="/images/sni-logo.png"
+ alt="SNI Logo"
+ className="w-4 h-5 object-contain object-top sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ <div className="gambarC ">
+ {product?.isTkdn && (
+ <ImageNext
+ src="/images/TKDN.png"
+ alt="TKDN"
+ className="w-11 h-6 object-contain object-top ml-1 sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ </div>
+ </div>
{product.variantTotal > 1 && (
<div className='absolute badge-gray bottom-1.5 left-1.5'>
{product.variantTotal} Varian
diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx
index e4a62abb..a8073036 100644
--- a/src/lib/product/components/ProductFilterDesktop.jsx
+++ b/src/lib/product/components/ProductFilterDesktop.jsx
@@ -21,6 +21,7 @@ import Image from '@/core/components/elements/Image/Image'
import { formatCurrency } from '@/core/utils/formatValue'
const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = null }) => {
+
const router = useRouter()
const { query } = router
const [order, setOrder] = useState(query?.orderBy)
@@ -102,7 +103,14 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu
}
params = _.pickBy(params, _.identity)
params = toQuery(params)
- router.push(`${prefixUrl}?${params}`)
+
+ const slug = Array.isArray(router.query.slug) ? router.query.slug[0] : router.query.slug;
+
+ if (slug) {
+ router.push(`${prefixUrl}/${slug}?${params}`)
+ } else {
+ router.push(`${prefixUrl}?${params}`)
+ }
}
diff --git a/src/lib/product/components/ProductFilterDesktopPromotion.jsx b/src/lib/product/components/ProductFilterDesktopPromotion.jsx
new file mode 100644
index 00000000..0815b881
--- /dev/null
+++ b/src/lib/product/components/ProductFilterDesktopPromotion.jsx
@@ -0,0 +1,132 @@
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import _ from 'lodash';
+import { toQuery } from 'lodash-contrib';
+import { Button } from '@chakra-ui/react';
+import { MultiSelect } from 'react-multi-select-component';
+
+const ProductFilterDesktop = ({ brands, categories, prefixUrl }) => {
+ const router = useRouter();
+ const { query } = router;
+ const [order, setOrder] = useState(query?.orderBy);
+ const [brandValues, setBrand] = useState([]);
+ const [categoryValues, setCategory] = useState([]);
+ const [priceFrom, setPriceFrom] = useState(query?.priceFrom);
+ const [priceTo, setPriceTo] = useState(query?.priceTo);
+ const [stock, setStock] = useState(query?.stock);
+ const [activeRange, setActiveRange] = useState(null);
+ const [isBrandDropdownClicked, setIsBrandDropdownClicked] = useState(false);
+ const [isCategoryDropdownClicked, setIsCategoryDropdownClicked] = useState(false);
+
+ // Effect to set brandValues from query parameter 'brand'
+ useEffect(() => {
+ const brandParam = query?.brand;
+ if (brandParam) {
+ const brandsArray = brandParam.split(',').map((b) => ({
+ label: b,
+ value: b,
+ }));
+ setBrand(brandsArray);
+ }
+
+ }, [query.brand]); // Trigger effect whenever query.brand changes
+
+ useEffect(() => {
+ const categoryParam = query?.category;
+ if (categoryParam) {
+ const categoriesArray = categoryParam.split(',').map((c) => ({
+ label: c,
+ value: c,
+ }));
+ setCategory(categoriesArray);
+ }
+ }, [query.category]); // Trigger effect whenever query.category changes
+
+ const handleSubmit = () => {
+ let params = {
+ q: router.query.q,
+ orderBy: order,
+ brand: brandValues.map((b) => b.value).join(','),
+ category: categoryValues.map((c) => c.value).join(','),
+ priceFrom,
+ priceTo,
+ stock: stock,
+ };
+ params = _.pickBy(params, _.identity);
+ params = toQuery(params);
+
+ const slug = Array.isArray(router.query.slug)
+ ? router.query.slug[0]
+ : router.query.slug;
+
+ if (slug) {
+ router.push(`${prefixUrl}/${slug}?${params}`);
+ } else {
+ router.push(`${prefixUrl}?${params}`);
+ }
+ };
+
+
+ const brandOptions = brands.map((brand) => ({
+ label: `${brand.brand} (${brand.qty})`,
+ value: brand.brand,
+ }));
+
+ const categoryOptions = categories.map((category) => ({
+ label: `${category.name} (${category.qty})`,
+ value: category.name,
+ }));
+
+ return (
+ <>
+ <div className='flex h-full w-[100%] justify-end '>
+ {/* Brand MultiSelect */}
+ <div className='mb-[20px] mr-4 w-64 h-full flex justify-start '>
+ <div className='relative'>
+ <label>Brand</label>
+ <div className='h-auto z-50 w-64 '>
+ <MultiSelect
+ options={brandOptions}
+ value={brandValues}
+ onChange={setBrand}
+ labelledBy='Select Brand'
+ onMenuToggle={(isOpen) => setIsBrandDropdownClicked(isOpen)}
+ hasSelectAll={false}
+ />
+ </div>
+ </div>
+ </div>
+
+ {/* Category MultiSelect */}
+ <div className='mb-[20px] mr-4 w-64 h-full flex justify-start '>
+ <div className='relative'>
+ <label>Kategori</label>
+ <div className=' h-auto w-64'>
+ <MultiSelect
+ options={categoryOptions}
+ value={categoryValues}
+ onChange={setCategory}
+ labelledBy='Select Kategori'
+ onMenuToggle={() =>
+ setIsCategoryDropdownClicked(!isCategoryDropdownClicked)
+ }
+ hasSelectAll={false}
+ />
+ </div>
+ </div>
+ </div>
+
+ {/* Apply Button */}
+ <div className='TOMBOL mb-1 h-24 flex justify-center items-center w-24'>
+ <div className=' bottom-1 pb-1 left-0 right-0 flex justify-center rounded' >
+ <Button colorScheme='red' width={"full"} onClick={handleSubmit}>
+ Terapkan
+ </Button>
+ </div>
+ </div>
+ </div>
+ </>
+ );
+};
+
+export default ProductFilterDesktop;
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index 08b64c13..b1a5d409 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -130,6 +130,7 @@ const ProductSearch = ({
brands.push({ brand, qty });
}
}
+
const categories = [];
for (
@@ -144,6 +145,7 @@ const ProductSearch = ({
categories.push({ name, qty });
}
}
+
const orderOptions = [
{ value: 'price-asc', label: 'Harga Terendah' },
diff --git a/src/lib/promo/components/Promocrumb.jsx b/src/lib/promo/components/Promocrumb.jsx
new file mode 100644
index 00000000..4f5cf346
--- /dev/null
+++ b/src/lib/promo/components/Promocrumb.jsx
@@ -0,0 +1,40 @@
+import { Breadcrumb as ChakraBreadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'
+import Link from 'next/link'
+import React from 'react'
+
+/**
+ * Renders a breadcrumb component with links to navigate through different pages.
+ *
+ * @param {Object} props - The props object containing the brand name.
+ * @param {string} props.brandName - The name of the brand to display in the breadcrumb.
+ * @return {JSX.Element} The rendered breadcrumb component.
+ */
+const Breadcrumb = ({ brandName }) => {
+ return (
+ <div className='container mx-auto py-4 md:py-6'>
+ <ChakraBreadcrumb>
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
+ Shop
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ {/* <BreadcrumbItem>
+ <BreadcrumbLink
+ as={Link}
+ href='/shop/promo'
+ className='!text-danger-500 whitespace-nowrap'
+ >
+ Promo
+ </BreadcrumbLink>
+ </BreadcrumbItem> */}
+
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink className='whitespace-nowrap'>{brandName}</BreadcrumbLink>
+ </BreadcrumbItem>
+ </ChakraBreadcrumb>
+ </div>
+ )
+}
+
+export default Breadcrumb
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
index 97b8a507..9bef895a 100644
--- a/src/lib/transaction/components/Transaction.jsx
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -4,7 +4,8 @@ import rejectImage from "../../../../public/images/reject.png"
import useTransaction from '../hooks/useTransaction';
import TransactionStatusBadge from './TransactionStatusBadge';
import Divider from '@/core/components/elements/Divider/Divider';
-import { useMemo, useRef, useState } from 'react';
+import { useEffect, useMemo, useRef, useState } from 'react';
+import ImageNext from 'next/image';
import {
downloadPurchaseOrder,
downloadQuotation,
@@ -45,7 +46,9 @@ const Transaction = ({ id }) => {
const [reason, setReason] = useState('');
const auth = useAuth();
const { transaction } = useTransaction({ id });
- const statusApprovalWeb = transaction.data?.approvalStep
+
+ const statusApprovalWeb = transaction.data?.approvalStep;
+
const { queryAirwayBill } = useAirwayBill({ orderId: id });
const [airwayBillPopup, setAirwayBillPopup] = useState(null);
@@ -55,6 +58,7 @@ const Transaction = ({ id }) => {
const [idAWB, setIdAWB] = useState(null);
const openUploadPo = () => setUploadPo(true);
const closeUploadPo = () => setUploadPo(false);
+
const submitUploadPo = async () => {
const file = poFile.current.files[0];
const name = poNumber.current.value;
@@ -84,7 +88,7 @@ const Transaction = ({ id }) => {
const closeCancelTransaction = () => setCancelTransaction(false);
const [rejectTransaction, setRejectTransaction] = useState(false);
-
+
const openRejectTransaction = () => setRejectTransaction(true);
const closeRejectTransaction = () => setRejectTransaction(false);
const submitCancelTransaction = async () => {
@@ -112,13 +116,13 @@ const Transaction = ({ id }) => {
await aprpoveApi({ id });
toast.success('Berhasil melanjutkan approval');
transaction.refetch();
- }
+ };
const handleReject = async () => {
- await rejectApi({ id });
- closeRejectTransaction()
- transaction.refetch();
- }
+ await rejectApi({ id });
+ closeRejectTransaction();
+ transaction.refetch();
+ };
const memoizeVariantGroupCard = useMemo(
() => (
@@ -285,7 +289,13 @@ const Transaction = ({ id }) => {
<MobileView>
<div className='p-4'>
- <StepApproval layer={2} status={'cancel'} className='ml-auto' />
+ {auth?.feature?.soApproval && (
+ <StepApproval
+ layer={statusApprovalWeb}
+ status={transaction?.data?.status}
+ className='ml-auto'
+ />
+ )}
</div>
<div className='flex flex-col gap-y-4 p-4'>
<DescriptionRow label='Status Transaksi'>
@@ -418,33 +428,43 @@ const Transaction = ({ id }) => {
<Divider />
<div className='p-4 pt-0'>
- {transaction.data?.status == 'draft' && auth?.feature.soApproval && (
- <div className='flex gap-x-2'>
- <button
- className='btn-yellow w-full'
- onClick={checkout}
- disabled={
- transaction.data?.status === 'cancel' ? true : false || auth?.webRole === statusApprovalWeb ? true : false
- }
- >
- Approve
- </button>
- <button
- className='btn-solid-red px-7 w-full'
- onClick={checkout}
- disabled={
- transaction.data?.status === 'cancel' ? true : false || auth?.webRole === statusApprovalWeb ? true : false
- }
- >
- Reject
+ {transaction.data?.status == 'draft' &&
+ auth?.feature.soApproval && (
+ <div className='flex gap-x-2'>
+ <button
+ className='btn-yellow w-full'
+ onClick={checkout}
+ disabled={
+ transaction.data?.status === 'cancel'
+ ? true
+ : false || auth?.webRole === statusApprovalWeb
+ ? true
+ : false
+ }
+ >
+ Approve
+ </button>
+ <button
+ className='btn-solid-red px-7 w-full'
+ onClick={checkout}
+ disabled={
+ transaction.data?.status === 'cancel'
+ ? true
+ : false || auth?.webRole === statusApprovalWeb
+ ? true
+ : false
+ }
+ >
+ Reject
+ </button>
+ </div>
+ )}
+ {transaction.data?.status == 'draft' &&
+ !auth?.feature?.soApproval && (
+ <button className='btn-yellow w-full mt-4' onClick={checkout}>
+ Lanjutkan Transaksi
</button>
- </div>
- )}
- {transaction.data?.status == 'draft' && !auth?.feature?.soApproval && (
- <button className='btn-yellow w-full mt-4' onClick={checkout}>
- Lanjutkan Transaksi
- </button>
- )}
+ )}
<button
className='btn-light w-full mt-4'
disabled={transaction.data?.status != 'draft'}
@@ -498,13 +518,20 @@ const Transaction = ({ id }) => {
Download
</button>
{transaction.data?.status == 'draft' &&
- auth?.feature?.soApproval && auth?.webRole && (
+ auth?.feature?.soApproval &&
+ auth?.webRole && (
<div className='flex gap-x-2'>
<button
className='btn-yellow'
onClick={handleApproval}
disabled={
- transaction.data?.status === 'cancel' ? true : false || auth?.webRole === statusApprovalWeb ? true : false || statusApprovalWeb < 1 ? true : false
+ transaction.data?.status === 'cancel'
+ ? true
+ : false || auth?.webRole === statusApprovalWeb
+ ? true
+ : false || statusApprovalWeb < 1
+ ? true
+ : false
}
>
Approve
@@ -513,7 +540,13 @@ const Transaction = ({ id }) => {
className='btn-solid-red px-7'
onClick={openRejectTransaction}
disabled={
- transaction.data?.status === 'cancel' ? true : false || auth?.webRole === statusApprovalWeb ? true : false || statusApprovalWeb < 1 ? true : false
+ transaction.data?.status === 'cancel'
+ ? true
+ : false || auth?.webRole === statusApprovalWeb
+ ? true
+ : false || statusApprovalWeb < 1
+ ? true
+ : false
}
>
Reject
@@ -526,15 +559,16 @@ const Transaction = ({ id }) => {
Lanjutkan Transaksi
</button>
)}
- {transaction.data?.status != 'draft' && !auth?.feature.soApproval && (
- <button
- className='btn-light'
- disabled={transaction.data?.status != 'waiting'}
- onClick={openCancelTransaction}
- >
- Batalkan Transaksi
- </button>
- )}
+ {transaction.data?.status != 'draft' &&
+ !auth?.feature.soApproval && (
+ <button
+ className='btn-light'
+ disabled={transaction.data?.status != 'waiting'}
+ onClick={openCancelTransaction}
+ >
+ Batalkan Transaksi
+ </button>
+ )}
</div>
<div className='grid grid-cols-2 gap-x-6 mt-6'>
@@ -549,7 +583,7 @@ const Transaction = ({ id }) => {
<div>Ketentuan Pembayaran</div>
<div>: {transaction?.data?.paymentTerm}</div>
- {!auth?.feature?.soApproval && (
+ {!auth?.feature?.soApproval ? (
<>
<div>Purchase Order</div>
<div>
@@ -569,6 +603,11 @@ const Transaction = ({ id }) => {
</button>
</div>
</>
+ ) : (
+ <>
+ <div>Site</div>
+ <div>: {transaction?.data?.sitePartner}</div>
+ </>
)}
</div>
</div>
@@ -672,11 +711,37 @@ const Transaction = ({ id }) => {
)}
className='w-[20%] flex-shrink-0'
>
- <Image
- src={product?.parent?.image}
- alt={product?.name}
- className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md'
- />
+ <div className='relative'>
+ <Image
+ src={product?.parent?.image}
+ alt={product?.name}
+ className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md'
+ />
+ <div className='absolute top-0 right-4 flex mt-3'>
+ <div className='gambarB '>
+ {product.isSni && (
+ <ImageNext
+ src='/images/sni-logo.png'
+ alt='SNI Logo'
+ className='w-2 h-4 object-contain object-top sm:h-4'
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ <div className='gambarC '>
+ {product.isTkdn && (
+ <ImageNext
+ src='/images/TKDN.png'
+ alt='TKDN'
+ className='w-5 h-4 object-contain object-top ml-1 sm:h-4'
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ </div>
+ </div>
</Link>
<div className='px-2 text-left'>
<Link
diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx
index 5a6dfb01..92bdd276 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -145,7 +145,7 @@ const Transactions = ({ context = '' }) => {
siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
};
const queryString = toQuery(query)
- const data = await transactionsApi({ query : queryString });
+ const data = await transactionsApi({ query: queryString });
return data;
};
@@ -349,7 +349,7 @@ const Transactions = ({ context = '' }) => {
</option>
))}
</select>
- ):( <div></div>) }
+ ) : (<div></div>)}
<form className='flex gap-x-1' onSubmit={handleSubmit}>
<input
@@ -382,6 +382,9 @@ const Transactions = ({ context = '' }) => {
<th>No. PO</th>
<th>Tanggal</th>
<th>Created By</th>
+ {auth?.feature?.soApproval && (
+ <th>Site</th>
+ )}
<th className='!text-left'>Salesperson</th>
<th className='!text-left'>Total</th>
<th>Status</th>
@@ -417,6 +420,9 @@ const Transactions = ({ context = '' }) => {
<td>{saleOrder.purchaseOrderName || '-'}</td>
<td>{saleOrder.dateOrder || '-'}</td>
<td>{saleOrder.address.customer?.name || '-'}</td>
+ {auth?.feature?.soApproval && (
+ <td>{saleOrder.sitePartner || '-'}</td>
+ )}
<td className='!text-left'>{saleOrder.sales}</td>
<td className='!text-left'>
{currencyFormat(saleOrder.amountTotal)}
diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx
index 5d95ee70..68cdf54f 100644
--- a/src/lib/variant/components/VariantCard.jsx
+++ b/src/lib/variant/components/VariantCard.jsx
@@ -11,6 +11,7 @@ import {useState } from 'react';
import rejectProductApi from '../../../lib/transaction/api/rejectProductApi'
// import {useTransaction} from 'C:\Users\Indoteknik\next-indoteknik\src\lib\transaction\hooks\useTransaction.js'
import useTransaction from '../../../lib/transaction/hooks/useTransaction';
+import ImageNext from 'next/image';
const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
const router = useRouter()
@@ -19,7 +20,10 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
const { transaction } = useTransaction({id});
const [isModalOpen, setIsModalOpen] = useState(false);
const [selectedProduct, setSelectedProduct] = useState(null);
- const [reason, setReason] = useState('');
+ const [reason, setReason] = useState('');
+
+
+
const addItemToCart = () => {
toast.success('Berhasil menambahkan ke keranjang', { duration: 1500 })
updateItemCart({
@@ -67,11 +71,39 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
const Card = () => (
<div className='flex gap-x-3'>
<div className='w-4/12 flex items-center gap-x-2'>
- <Image
+
+ <div className="relative">
+ <Image
src={product.parent.image}
alt={product.parent.name}
className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md'
/>
+ <div className="absolute top-0 right-4 flex mt-3">
+ <div className="gambarB ">
+ {product.isSni && (
+ <ImageNext
+ src="/images/sni-logo.png"
+ alt="SNI Logo"
+ className="w-2 h-5 object-contain object-top sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ <div className="gambarC ">
+ {product.isTkdn && (
+ <ImageNext
+ src="/images/TKDN.png"
+ alt="TKDN"
+ className="w-5 h-6 object-contain object-top ml-1 mr-1 sm:h-6"
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ </div>
+ </div>
+
</div>
<div className='w-8/12 flex flex-col'>
<p className='product-card__title wrap-line-ellipsis-2'>{product.parent.name}</p>