diff options
| author | Rafi Zadanly <rafizadanly@gmail.com> | 2022-12-15 16:37:45 +0700 |
|---|---|---|
| committer | Rafi Zadanly <rafizadanly@gmail.com> | 2022-12-15 16:37:45 +0700 |
| commit | 4a615aae5f29ed8c0ad3631a8510df57b80cae94 (patch) | |
| tree | a3dced877ba73e4cd5907076cbcfa2fe369bc33d /src | |
| parent | 2c58745807110ba234e1a9ec939457e641fff469 (diff) | |
feature checbox add to process in cart
Diffstat (limited to 'src')
| -rw-r--r-- | src/pages/shop/cart.js | 138 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].js | 8 | ||||
| -rw-r--r-- | src/styles/globals.css | 53 |
3 files changed, 158 insertions, 41 deletions
diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js index 5e7ff822..653f1ac4 100644 --- a/src/pages/shop/cart.js +++ b/src/pages/shop/cart.js @@ -2,18 +2,23 @@ import { useEffect, useState } from "react"; import Header from "../../components/Header"; import Layout from "../../components/Layout"; import Link from "../../components/Link"; -import { createOrUpdateItemCart, deleteItemCart, getCart, getItemCart } from "../../helpers/cart"; +import { createOrUpdateItemCart, deleteItemCart, getCart } from "../../helpers/cart"; import ChevronLeftIcon from "../../icons/chevron-left.svg"; import MinusIcon from "../../icons/minus.svg"; import PlusIcon from "../../icons/plus.svg"; +import TrashIcon from "../../icons/trash.svg"; import { LazyLoadImage } from "react-lazy-load-image-component"; - -import 'react-lazy-load-image-component/src/effects/blur.css'; import apiOdoo from "../../helpers/apiOdoo"; import currencyFormat from "../../helpers/currencyFormat"; +import 'react-lazy-load-image-component/src/effects/blur.css'; +import { createSlug } from "../../helpers/slug"; + export default function Cart() { const [products, setProducts] = useState([]); + const [totalPriceBeforeTax, setTotalPriceBeforeTax] = useState(0); + const [totalTaxAmount, setTotalTaxAmount] = useState(0); + const [totalDiscountAmount, setTotalDiscountAmount] = useState(0); const getProducts = async () => { let cart = getCart(); @@ -23,7 +28,8 @@ export default function Cart() { let dataProducts = await apiOdoo('GET', `/api/v1/product_variant/${productIds}`); dataProducts = dataProducts.map((product) => ({ ...product, - quantity: cart[product.id].quantity + quantity: cart[product.id].quantity, + to_process: false })); setProducts(dataProducts); } @@ -33,13 +39,31 @@ export default function Cart() { getProducts(); }, []); + useEffect(() => { + const productsToProcess = products.filter((product) => product.to_process == true); + if (products.length > 0) { + + let calculateTotalPriceBeforeTax = 0; + let calculateTotalTaxAmount = 0; + let calculateTotalDiscountAmount = 0; + productsToProcess.forEach(product => { + let priceBeforeTax = product.price.price / 1.11; + calculateTotalPriceBeforeTax += priceBeforeTax * product.quantity; + calculateTotalTaxAmount += (product.price.price - priceBeforeTax) * product.quantity; + calculateTotalDiscountAmount += (product.price.price - product.price.price_discount) * product.quantity; + }); + setTotalPriceBeforeTax(calculateTotalPriceBeforeTax); + setTotalTaxAmount(calculateTotalTaxAmount); + setTotalDiscountAmount(calculateTotalDiscountAmount); + } + }, [products]); + const updateCart = (productId, quantity) => { let productIndexToUpdate = products.findIndex((product) => product.id == productId); if (quantity != '') createOrUpdateItemCart(productId, quantity); - setProducts((products) => { - products[productIndexToUpdate].quantity = quantity; - return [...products]; - }); + let productsToUpdate = products; + productsToUpdate[productIndexToUpdate].quantity = quantity; + setProducts([...productsToUpdate]); }; const blurQuantity = (productId, quantity) => { @@ -49,7 +73,9 @@ export default function Cart() { const updateQuantity = (productId, quantity) => { quantity = quantity == '' ? '' : parseInt(quantity); - updateCart(productId, quantity); + if (quantity > 0) { + updateCart(productId, quantity); + } }; const plusQuantity = (productId) => { @@ -61,15 +87,22 @@ export default function Cart() { const minusQuantity = (productId) => { let productIndexToUpdate = products.findIndex((product) => product.id == productId); let quantity = products[productIndexToUpdate].quantity - 1; - if (quantity <= 0) { - deleteItemCart(productId); - setProducts((products) => { - products.splice(productIndexToUpdate, 1); - return [...products]; - }); - } else { - updateCart(productId, quantity); - } + updateCart(productId, quantity); + } + + const deleteItem = (productId) => { + let productIndexToUpdate = products.findIndex((product) => product.id == productId); + let productsToUpdate = products; + productsToUpdate.splice(productIndexToUpdate, 1); + setProducts([...productsToUpdate]); + deleteItemCart(productId); + } + + const toggleProductToProcess = (productId) => { + let productIndexToUpdate = products.findIndex((product) => product.id == productId); + let productsToUpdate = products; + productsToUpdate[productIndexToUpdate].to_process = !productsToUpdate[productIndexToUpdate].to_process; + setProducts([...productsToUpdate]); } return ( @@ -86,14 +119,14 @@ export default function Cart() { <div className="h-0.5 w-full bg-gray_r-7"></div> </div> <div className="flex gap-x-2 items-center"> - <div className="bg-gray_r-3 leading-none p-2 rounded-full w-7 text-center text-gray_r-11 text-caption-2">2</div> + <div className="bg-gray_r-4 leading-none p-2 rounded-full w-7 text-center text-gray_r-11 text-caption-2">2</div> <p className="font-medium text-gray_r-11 text-caption-2">Pembayaran</p> </div> <div className="flex-1 flex items-center"> <div className="h-0.5 w-full bg-gray_r-7"></div> </div> <div className="flex gap-x-2 items-center"> - <div className="bg-gray_r-3 leading-none p-2 rounded-full w-7 text-center text-gray_r-11 text-caption-2">3</div> + <div className="bg-gray_r-4 leading-none p-2 rounded-full w-7 text-center text-gray_r-11 text-caption-2">3</div> <p className="font-medium text-gray_r-11 text-caption-2">Selesai</p> </div> </div> @@ -110,14 +143,18 @@ export default function Cart() { {/* [End] Title */} {/* [Start] Product List */} - <div className="flex flex-col gap-y-6"> + <div className="flex flex-col gap-y-6 mb-8"> {products.map((product, index) => ( <div className="flex gap-x-3" key={index}> - <div className="w-4/12"> + <div className="w-4/12 flex items-center gap-x-2"> + <button + className={'p-2 rounded border ' + (product.to_process ? 'border-yellow_r-9 bg-yellow_r-9' : 'border-gray_r-6')} + onClick={() => toggleProductToProcess(product.id)} + ></button> <LazyLoadImage effect="blur" src={product.parent.image ? product.parent.image : '/images/noimage.jpeg'} alt={product.parent.name} className="object-contain object-center border border-gray_r-6 h-32 w-full rounded-md" /> </div> <div className="w-8/12 flex flex-col"> - <Link href="/" className="product-card__title wrap-line-ellipsis-2"> + <Link href={'/shop/product/' + createSlug(product.parent.name, product.parent.id)} className="product-card__title wrap-line-ellipsis-2"> {product.parent.name} </Link> <p className="text-caption-1 text-gray_r-11 mt-1">{product.code ? product.code : '-'}</p> @@ -134,17 +171,27 @@ export default function Cart() { <div className="flex items-center"> <p className="mr-auto text-caption-1 text-gray_r-12 font-bold">{currencyFormat(product.quantity * product.price.price_discount)}</p> <div className="flex gap-x-2"> - <button className="btn-light p-1 rounded-full" onClick={() => minusQuantity(product.id)}> - <MinusIcon className="stroke-gray_r-12 w-3"/> + <button + className="btn-red p-1 rounded" + onClick={() => deleteItem(product.id)} + > + <TrashIcon className="stroke-red_r-12 w-3"/> + </button> + <button + className="btn-light p-1 rounded" + disabled={product.quantity == 1} + onClick={() => minusQuantity(product.id)} + > + <MinusIcon className={'stroke-gray_r-12 w-3' + (product.quantity == 1 ? ' stroke-gray_r-11' : '')}/> </button> <input type="number" - className="bg-transparent border-none w-4 text-center outline-none" + className="bg-transparent border-none w-6 text-center outline-none" onBlur={(e) => blurQuantity(product.id, e.target.value)} onChange={(e) => updateQuantity(product.id, e.target.value)} value={product.quantity} /> - <button className="btn-light p-1 rounded-full" onClick={() => plusQuantity(product.id)}> + <button className="btn-light p-1 rounded" onClick={() => plusQuantity(product.id)}> <PlusIcon className="stroke-gray_r-12 w-3"/> </button> </div> @@ -155,6 +202,43 @@ export default function Cart() { </div> {/* [End] Product List */} + {/* [Start] Review Order */} + <div className="p-4 border border-gray_r-6 rounded-md mb-4"> + <h2>Ringkasan Pesanan</h2> + <hr className="my-4 border-gray_r-6"/> + <div className="flex flex-col gap-y-4"> + <div className="flex gap-x-2 justify-between"> + <p>Harga Sebelum PPN</p> + <p className="font-medium">{currencyFormat(totalPriceBeforeTax)}</p> + </div> + <div className="flex gap-x-2 justify-between"> + <p>PPN 11%</p> + <p className="font-medium">{currencyFormat(totalTaxAmount)}</p> + </div> + <div className="flex gap-x-2 justify-between"> + <p>Total Diskon</p> + <p className="font-medium text-red_r-11">- {currencyFormat(totalDiscountAmount)}</p> + </div> + </div> + <hr className="my-4 border-gray_r-6"/> + <div className="flex gap-x-2 justify-between mb-4"> + <p>Total Harga</p> + <p className="font-medium text-yellow_r-11">{currencyFormat(totalPriceBeforeTax + totalTaxAmount - totalDiscountAmount)}</p> + </div> + <p className="text-caption-2 text-gray_r-10 mb-2">*) Belum termasuk biaya pengiriman</p> + <p className="text-caption-2 text-gray_r-10 leading-5"> + Dengan melakukan pembelian melalui website Indoteknik, saya menyetujui <Link href="/">Syarat & Ketentuan</Link> yang berlaku + </p> + </div> + {/* [End] Review Order */} + + {/* [Start] Submit Button */} + <div className="flex gap-x-3"> + <button className="flex-1 btn-light">Quotation (1)</button> + <button className="flex-1 btn-yellow">Bayar (1)</button> + </div> + {/* [End] Submit Button */} + </div> </Layout> </> diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js index cabda175..9bb76fb6 100644 --- a/src/pages/shop/product/[slug].js +++ b/src/pages/shop/product/[slug].js @@ -140,7 +140,13 @@ export default function ProductDetail({ product }) { <div className="flex gap-x-2 mt-2"> <button className="btn-light w-full">+ Quotation</button> - <button className="btn-yellow w-full" onClick={addItemToCart} disabled={(product.lowest_price.price == 0 ? true : false)}>+ Keranjang</button> + <button + className="btn-yellow w-full" + onClick={addItemToCart} + disabled={(product.lowest_price.price == 0 ? true : false)} + > + + Keranjang + </button> </div> <div className="mt-10"> diff --git a/src/styles/globals.css b/src/styles/globals.css index 3ecf04b8..1224d661 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -14,6 +14,16 @@ html, body { } @layer base { + input[type="number"]::-webkit-inner-spin-button, + input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; + } + + input[type=number] { + -moz-appearance:textfield; + } + h1, .h1 { @apply text-h-md @@ -104,34 +114,48 @@ html, body { ; } - .btn-yellow { - @apply + .btn-yellow, + .btn-light, + .btn-red { + @apply block w-fit p-3 - bg-yellow_r-9 - border-yellow_r-9 rounded border text-center + font-medium + ease-linear + duration-150 + ; + } + + .btn-yellow { + @apply + bg-yellow_r-9 + border-yellow_r-9 disabled:text-gray_r-10 disabled:bg-yellow_r-7 disabled:border-yellow_r-7 - ease-linear - duration-150 + ; + } + + .btn-red { + @apply + bg-red_r-3 + border-red_r-6 + text-red_r-12 + disabled:text-red_r-10 + disabled:bg-red_r-6 ; } .btn-light { @apply - block - w-fit - p-3 bg-gray_r-3 border-gray_r-6 - rounded - border - text-center + disabled:text-gray_r-10 + disabled:bg-gray_r-6 ; } @@ -299,7 +323,10 @@ html, body { } .lazy-load-image-background { - @apply !block; + @apply + !block + w-full + ; } .swiper-pagination-bullet-active { |
