summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-10-07 12:14:49 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-10-07 12:14:49 +0700
commit7db9105b7d2ccabb16103be5f0b83c0f4ba3569a (patch)
tree17dcdd9b046943d9001033f9618d3a825a6230ef /src
parenta9c90f0c7cb3b6e702c66dd26851c9ec364017c6 (diff)
<Miqdad> match prod detail from google ads w/ prod detail website
Diffstat (limited to 'src')
-rw-r--r--src/lib/product/components/Product/ProductDesktopVariant.jsx2
-rw-r--r--src/lib/product/components/Product/ProductMobileVariant.jsx162
2 files changed, 106 insertions, 58 deletions
diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx
index e770d66b..6d6e15f7 100644
--- a/src/lib/product/components/Product/ProductDesktopVariant.jsx
+++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx
@@ -482,7 +482,7 @@ const ProductDesktopVariant = ({
)}
</h3>
)}
- <div className='flex justify-between items-center py-5 px-3'>
+ <div className='flex gap-x-5 items-center py-5'>
<div className='relative flex items-center'>
<button
type='button'
diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx
index d1e7c7e9..c3c8a584 100644
--- a/src/lib/product/components/Product/ProductMobileVariant.jsx
+++ b/src/lib/product/components/Product/ProductMobileVariant.jsx
@@ -27,6 +27,8 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
let auth = getAuth();
const [quantity, setQuantity] = useState('1');
const [selectedVariant, setSelectedVariant] = useState(product.id);
+ const [quantityInput, setQuantityInput] = useState(String(1));
+ const [qtyPickUp, setQtyPickUp] = useState(0);
const [informationTab, setInformationTab] = useState(
informationTabOptions[0].value
);
@@ -63,30 +65,33 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
}
}, [selectedVariant, product]);
- const validAction = () => {
- let isValid = true;
+ const validAction = (q) => {
if (!selectedVariant) {
toast.error('Pilih varian terlebih dahulu');
- isValid = false;
+ return false;
}
- if (!quantity || quantity < 1 || isNaN(parseInt(quantity))) {
+ if (!Number.isInteger(q) || q < 1) {
toast.error('Jumlah barang minimal 1');
- isValid = false;
+ return false;
}
- return isValid;
+ return true;
};
+ const getQty = () => Math.max(1, toInt(quantityInput));
+
const handleClickCart = async () => {
+ const q = getQty();
+
if (!auth) {
router.push(`/login?next=/shop/product/${slug}?srsltid=${srsltid}`);
return;
}
+ if (!validAction(q)) return;
- if (!validAction()) return;
- gtagAddToCart(activeVariant, quantity);
+ gtagAddToCart(activeVariant, q);
updateItemCart({
productId: product.id,
- quantity,
+ quantity: q,
programLineId: null,
selected: true,
source: null,
@@ -95,37 +100,29 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
};
const handleClickBuy = async () => {
- let isLoggedIn = typeof auth === 'object';
+ const q = getQty();
+ 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);
+ const t = setInterval(() => {
+ const newAuth = getAuth();
+ if (typeof newAuth === 'object') {
+ auth = newAuth;
+ clearInterval(t);
resolve(null);
}
}, 500);
});
}
- if (!validAction()) return;
+ if (!validAction(q)) return;
updateItemCart({
productId: product.id,
- quantity,
+ quantity: q,
programLineId: null,
selected: true,
source: 'buy',
@@ -133,8 +130,21 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
router.push(`/shop/checkout?source=buy`);
};
+ const toInt = (v) => {
+ const n = parseInt(String(v ?? '').trim(), 10);
+ return Number.isFinite(n) ? n : 0;
+ };
+
+ const validQuantity = (q) => {
+ if (!Number.isInteger(q) || q < 1) {
+ toast.error('Jumlah barang minimal 1');
+ return false;
+ }
+ return true;
+ };
+
const handleButton = (variant) => {
- const quantity = quantityInput;
+ const quantity = Math.max(1, toInt(quantityInput)); // clamp min 1
if (!validQuantity(quantity)) return;
updateItemCart({
@@ -168,9 +178,10 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
return (
<MobileView>
- <div
- className={`px-4 block md:sticky md:top-[150px] md:py-6 fixed bottom-0 left-0 right-0 bg-white p-2 z-10 pb-6 pt-6 rounded-lg shadow-[rgba(0,0,4,0.1)_0px_-4px_4px_0px] `}
- >
+ {/* PRICE & ACTIONS: tetap punyamu, hanya hapus input number lama */}
+ {/* ===== BAR BAWAH (fixed) ===== */}
+ <div className='px-4 fixed bottom-0 left-0 right-0 bg-white z-10 pb-6 pt-4 rounded-t-2xl shadow-[rgba(0,0,4,0.1)_0px_-4px_4px_0px]'>
+ {/* HARGA & PPN (logikamu tetap) */}
{activeVariant.isFlashSale &&
activeVariant?.price?.discountPercentage > 0 ? (
<>
@@ -225,58 +236,94 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
)}
</div>
)}
- <div className=''>
- <div className='mt-4 mb-2'>Jumlah</div>
- <div className='flex gap-x-3'>
- <div className='w-2/12'>
+
+ {/* ⬇️ TAMBAHKAN BLOK INI DI DALAM BAR: STOK & STEPPER */}
+ <div className='grid grid-cols-12 items-center gap-3 mt-3'>
+ <div className='col-span-7'>
+ <div
+ className={`text-[14px] ${
+ product?.sla?.qty < 10 ? 'text-red-600 font-medium' : ''
+ }`}
+ >
+ Stock : {activeVariant?.stock ?? 0}
+ </div>
+ {qtyPickUp > 0 && (
+ <div className='text-[16px] mt-0.5 text-red-500 italic'>
+ * {qtyPickUp} barang bisa di pickup
+ </div>
+ )}
+ </div>
+ <div className='col-span-5 flex justify-end'>
+ <div className='inline-flex items-stretch border rounded-xl overflow-hidden'>
+ <button
+ type='button'
+ className='h-10 w-10 grid place-items-center text-gray-700 hover:bg-gray-100 active:scale-95'
+ onClick={() =>
+ setQuantityInput(
+ String(Math.max(1, Number(quantityInput || 1) - 1))
+ )
+ }
+ aria-label='Kurangi'
+ >
+ <span className='text-2xl leading-none'>–</span>
+ </button>
<input
- name='quantity'
type='number'
- className='form-input'
- value={quantity}
- onChange={(e) => setQuantity(e.target.value)}
+ min={1}
+ value={quantityInput}
+ onChange={(e) => setQuantityInput(e.target.value)}
+ className='h-10 w-16 text-center text-lg outline-none border-x
+ [appearance:textfield]
+ [&::-webkit-outer-spin-button]:appearance-none
+ [&::-webkit-inner-spin-button]:appearance-none'
/>
+ <button
+ type='button'
+ className='h-10 w-10 grid place-items-center text-gray-700 hover:bg-gray-100 active:scale-95'
+ onClick={() =>
+ setQuantityInput(String(Number(quantityInput || 1) + 1))
+ }
+ aria-label='Tambah'
+ >
+ <span className='text-2xl leading-none'>+</span>
+ </button>
</div>
+ </div>
+ </div>
+
+ {/* TOMBOL AKSI */}
+ <div className='mt-3'>
+ <div className='flex gap-x-3'>
<Button
- onClick={() => handleClickCart(product.id)}
+ onClick={() =>
+ handleClickCart(product.id, Number(quantityInput || 1))
+ }
className='flex-1'
colorScheme='red'
- variant={'outline'}
+ variant='outline'
>
Keranjang
</Button>
<Button
- onClick={() => handleClickBuy(product.id)}
+ onClick={() =>
+ handleClickBuy(product.id, Number(quantityInput || 1))
+ }
className='flex-1'
colorScheme='red'
>
Beli
</Button>
- {/* <button
- type='button'
- className='btn-yellow flex-1'
- onClick={handleClickCart}
- >
- Keranjang
- </button>
- <button
- type='button'
- className='btn-solid-red flex-1'
- onClick={handleClickBuy}
- >
- Beli
- </button> */}
</div>
+
<Button
onClick={() => handleButton(product.id)}
- color={'red'}
+ color='red'
colorScheme='white'
className='w-full border-2 p-2 gap-1 mt-2 hover:bg-slate-100 flex items-center'
>
<ImageNext
src='/images/writing.png'
alt='penawaran instan'
- className=''
width={25}
height={25}
/>
@@ -284,6 +331,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
</Button>
</div>
</div>
+
<Image
src={product.image + '?variant=True'}
alt={product.name}