summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRafi Zadanly <rafizadanly@gmail.com>2022-12-14 17:48:03 +0700
committerRafi Zadanly <rafizadanly@gmail.com>2022-12-14 17:48:03 +0700
commitbd4008ac5c2a22c1d99239ba0691cfb8ef0e9aea (patch)
treec2f1289cfaa68ba5154e695f26d80278f42208f1 /src
parent4e2b85a16b032df07686fd044ba9183afceb8b11 (diff)
add to cart, cart page, change cart item quantity
Diffstat (limited to 'src')
-rw-r--r--src/helpers/cart.js39
-rw-r--r--src/icons/minus.svg3
-rw-r--r--src/icons/plus.svg4
-rw-r--r--src/pages/shop/brands/[slug].js4
-rw-r--r--src/pages/shop/cart.js167
-rw-r--r--src/pages/shop/product/[slug].js4
6 files changed, 163 insertions, 58 deletions
diff --git a/src/helpers/cart.js b/src/helpers/cart.js
index 07e47324..8712c03a 100644
--- a/src/helpers/cart.js
+++ b/src/helpers/cart.js
@@ -1,7 +1,7 @@
const getCart = () => {
const cart = localStorage.getItem('cart');
if (cart) return JSON.parse(cart);
- return [];
+ return {};
}
const setCart = (cart) => {
@@ -9,18 +9,18 @@ const setCart = (cart) => {
return true;
}
-const getItemIndex = (product_id) => {
- const cart = getCart();
- return cart.findIndex((item) => item.product_id == product_id);
+const getItemCart = (product_id) => {
+ let cart = getCart();
+ return cart[product_id];
}
-const addToCart = (product_id, quantity) => {
+const createOrUpdateItemCart = (product_id, quantity) => {
let cart = getCart();
- let itemIndexByProductId = getItemIndex(product_id);
- if (itemIndexByProductId > -1) {
- updateItemCart(product_id, quantity);
+ let isFoundInCart = cart[product_id];
+ if (isFoundInCart) {
+ cart[product_id].quantity = quantity;
} else {
- cart.push({ product_id, quantity });
+ cart[product_id] = { product_id, quantity };
}
setCart(cart);
return true;
@@ -28,27 +28,14 @@ const addToCart = (product_id, quantity) => {
const deleteItemCart = (product_id) => {
let cart = getCart();
- let itemIndexByProductId = getItemIndex(product_id);
- if (itemIndexByProductId > -1) {
- cart.splice(itemIndexByProductId, 1)
- }
- setCart(cart);
- return true;
-}
-
-const updateItemCart = (product_id, quantity) => {
- let cart = getCart();
- let itemIndexByProductId = getItemIndex(product_id);
- if (itemIndexByProductId > -1) {
- cart[itemIndexByProductId].quantity += quantity;
- }
+ delete cart[product_id]
setCart(cart);
return true;
}
export {
getCart,
- addToCart,
- deleteItemCart,
- updateItemCart
+ getItemCart,
+ createOrUpdateItemCart,
+ deleteItemCart
} \ No newline at end of file
diff --git a/src/icons/minus.svg b/src/icons/minus.svg
new file mode 100644
index 00000000..12a10199
--- /dev/null
+++ b/src/icons/minus.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-minus">
+ <line x1="5" y1="12" x2="19" y2="12"></line>
+</svg> \ No newline at end of file
diff --git a/src/icons/plus.svg b/src/icons/plus.svg
new file mode 100644
index 00000000..2923c684
--- /dev/null
+++ b/src/icons/plus.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus">
+ <line x1="12" y1="5" x2="12" y2="19"></line>
+ <line x1="5" y1="12" x2="19" y2="12"></line>
+</svg> \ No newline at end of file
diff --git a/src/pages/shop/brands/[slug].js b/src/pages/shop/brands/[slug].js
index 320c4454..b04d2715 100644
--- a/src/pages/shop/brands/[slug].js
+++ b/src/pages/shop/brands/[slug].js
@@ -88,8 +88,8 @@ export default function BrandDetail({
<button className="btn-light py-2 flex items-center gap-x-2 mb-2" onClick={() => setActiveFilter(true)}>
<FilterIcon className="w-4 h-4" /> <span>Filter</span>
</button>
- <h1>Produk</h1>
- <div className="text-caption mb-4">
+ <h1 className="mb-2">Produk</h1>
+ <div className="text-caption-1 mb-4">
{productFound > 0 ? (
<>
Menampilkan&nbsp;
diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js
index 635d4efd..5e7ff822 100644
--- a/src/pages/shop/cart.js
+++ b/src/pages/shop/cart.js
@@ -1,49 +1,160 @@
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import Header from "../../components/Header";
import Layout from "../../components/Layout";
import Link from "../../components/Link";
-import { getCart } from "../../helpers/cart";
+import { createOrUpdateItemCart, deleteItemCart, getCart, getItemCart } from "../../helpers/cart";
import ChevronLeftIcon from "../../icons/chevron-left.svg";
+import MinusIcon from "../../icons/minus.svg";
+import PlusIcon from "../../icons/plus.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";
export default function Cart() {
+ const [products, setProducts] = useState([]);
+
+ const getProducts = async () => {
+ let cart = getCart();
+ let productIds = Object.keys(cart);
+ if (productIds.length > 0) {
+ productIds = productIds.join(',');
+ let dataProducts = await apiOdoo('GET', `/api/v1/product_variant/${productIds}`);
+ dataProducts = dataProducts.map((product) => ({
+ ...product,
+ quantity: cart[product.id].quantity
+ }));
+ setProducts(dataProducts);
+ }
+ }
+
useEffect(() => {
- console.log(getCart());
- })
+ getProducts();
+ }, []);
+
+ 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];
+ });
+ };
+
+ const blurQuantity = (productId, quantity) => {
+ quantity = quantity == ('' || 0) ? 1 : parseInt(quantity);
+ updateCart(productId, quantity);
+ };
+
+ const updateQuantity = (productId, quantity) => {
+ quantity = quantity == '' ? '' : parseInt(quantity);
+ updateCart(productId, quantity);
+ };
+
+ const plusQuantity = (productId) => {
+ let productIndexToUpdate = products.findIndex((product) => product.id == productId);
+ let quantity = products[productIndexToUpdate].quantity + 1;
+ updateCart(productId, quantity);
+ }
+
+ 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);
+ }
+ }
+
return (
<>
<Header title={`Keranjang Belanja - Indoteknik`}/>
<Layout>
- <div className="p-4">
- {/* Progress Bar */}
- <div className="bg-gray_r-2 flex gap-x-2 p-4 rounded-md mb-4">
- <div className="flex gap-x-2 items-center">
- <div className="bg-yellow_r-9 leading-none p-2 rounded-full w-7 text-center text-gray_r-12 text-caption-2">1</div>
- <p className="font-medium text-gray_r-12 text-caption-2">Keranjang</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">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>
- <p className="font-medium text-gray_r-11 text-caption-2">Selesai</p>
- </div>
+ {/* jsx-start: Progress Bar */}
+ <div className="bg-gray_r-2 flex gap-x-2 p-4 rounded-md">
+ <div className="flex gap-x-2 items-center">
+ <div className="bg-yellow_r-9 leading-none p-2 rounded-full w-7 text-center text-gray_r-12 text-caption-2">1</div>
+ <p className="font-medium text-gray_r-12 text-caption-2">Keranjang</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">2</div>
+ <p className="font-medium text-gray_r-11 text-caption-2">Pembayaran</p>
</div>
- {/* [End] Progress Bar */}
- {/* Title */}
- <div className="flex gap-x-2">
+ <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>
+ <p className="font-medium text-gray_r-11 text-caption-2">Selesai</p>
+ </div>
+ </div>
+ {/* [End] Progress Bar */}
+ <div className="p-4">
+
+ {/* [Start] Title */}
+ <div className="flex gap-x-2 mb-8">
<Link href="/" className="pr-2">
<ChevronLeftIcon className="w-6 stroke-gray_r-12"/>
</Link>
<h1>Keranjang Saya</h1>
</div>
{/* [End] Title */}
+
+ {/* [Start] Product List */}
+ <div className="flex flex-col gap-y-6">
+ {products.map((product, index) => (
+ <div className="flex gap-x-3" key={index}>
+ <div className="w-4/12">
+ <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">
+ {product.parent.name}
+ </Link>
+ <p className="text-caption-1 text-gray_r-11 mt-1">{product.code ? product.code : '-'}</p>
+ <div className="flex flex-wrap gap-x-1 items-center mb-2 mt-auto">
+ <p className="text-caption-1 text-gray_r-12">{currencyFormat(product.price.price_discount)}</p>
+ {product.price.discount_percentage > 0 ? (
+ <>
+ <span className="badge-red">{product.price.discount_percentage}%</span>
+ <p className="text-caption-2 text-gray_r-11 line-through">{currencyFormat(product.price.price)}</p>
+ </>
+ ) : ''}
+
+ </div>
+ <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>
+ <input
+ type="number"
+ className="bg-transparent border-none w-4 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)}>
+ <PlusIcon className="stroke-gray_r-12 w-3"/>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ {/* [End] Product List */}
+
</div>
</Layout>
</>
diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js
index e44cfeca..cabda175 100644
--- a/src/pages/shop/product/[slug].js
+++ b/src/pages/shop/product/[slug].js
@@ -9,7 +9,7 @@ import { LazyLoadImage } from "react-lazy-load-image-component";
import "react-lazy-load-image-component/src/effects/blur.css";
import ProductSlider from "../../../components/product/ProductSlider";
import Layout from "../../../components/Layout";
-import { addToCart } from "../../../helpers/cart";
+import { createOrUpdateItemCart } from "../../../helpers/cart";
export async function getServerSideProps( context ) {
const { slug } = context.query;
@@ -83,7 +83,7 @@ export default function ProductDetail({ product }) {
let addItemToCart = () => {
if (quantity > 0) {
- addToCart(activeVariant.id, parseInt(quantity));
+ createOrUpdateItemCart(activeVariant.id, parseInt(quantity));
}
return true;
}