diff options
| author | Rafi Zadanly <rafizadanly@gmail.com> | 2022-12-16 11:22:45 +0700 |
|---|---|---|
| committer | Rafi Zadanly <rafizadanly@gmail.com> | 2022-12-16 11:22:45 +0700 |
| commit | f45dee703450c42521884f8e0da8ae49f652b8c6 (patch) | |
| tree | 184ef403a9808e05823e9e2a93d0e24dae7b385c | |
| parent | a03d150a2816ed7f901d3acf0ceb26c4025365e1 (diff) | |
item cart delete confirmation
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | src/components/ConfirmAlert.js | 26 | ||||
| -rw-r--r-- | src/pages/_app.js | 15 | ||||
| -rw-r--r-- | src/pages/shop/brands.js | 2 | ||||
| -rw-r--r-- | src/pages/shop/cart.js | 53 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].js | 4 | ||||
| -rw-r--r-- | src/styles/globals.css | 10 |
7 files changed, 85 insertions, 27 deletions
diff --git a/package.json b/package.json index dfef8f27..9d8e529f 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,9 @@ "nodemailer": "^6.8.0", "react": "18.2.0", "react-dom": "18.2.0", + "react-hot-toast": "^2.4.0", "react-infinite-scroll-component": "^6.1.0", "react-lazy-load-image-component": "^1.5.5", - "react-toastify": "^9.1.1", "swiper": "^8.4.4" }, "devDependencies": { diff --git a/src/components/ConfirmAlert.js b/src/components/ConfirmAlert.js new file mode 100644 index 00000000..3a8f796d --- /dev/null +++ b/src/components/ConfirmAlert.js @@ -0,0 +1,26 @@ +import { useState } from "react"; + +const ConfirmAlert = ({ + title, + caption, + show, + onClose, + onSubmit, +}) => { + return ( + <> + {show && ( + <div className="menu-overlay" onClick={onClose}></div> + )} + <div className={"p-4 rounded border bg-white border-gray_r-6 fixed top-[50%] left-[50%] translate-x-[-50%] z-[70] w-[80%] translate-y-[-50%] " + (show ? "block" : "hidden")}> + <p className="h2 mb-4">{title}</p> + <div className="flex gap-x-2"> + <button className="flex-1 btn-light" onClick={onClose}>Batal</button> + <button className="flex-1 btn-yellow" onClick={onSubmit}>Hapus</button> + </div> + </div> + </> + ); +}; + +export default ConfirmAlert;
\ No newline at end of file diff --git a/src/pages/_app.js b/src/pages/_app.js index 23172bfd..41d6c2f6 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -1,22 +1,19 @@ import '../styles/globals.css'; import NextProgress from 'next-progress'; -import { ToastContainer, Slide } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; import { useRouter } from 'next/router'; import { AnimatePresence } from 'framer-motion'; +import { Toaster } from "react-hot-toast"; function MyApp({ Component, pageProps }) { const router = useRouter(); return ( <> - <ToastContainer - position='top-center' - autoClose={5000} - theme='light' - closeOnClick={false} - transition={Slide} - limit={1} + <Toaster + position="top-center" + toastOptions={{ + duration: 3000, + }} /> <NextProgress color="#D7A30A" options={{ showSpinner: false }} /> <AnimatePresence diff --git a/src/pages/shop/brands.js b/src/pages/shop/brands.js index 6c1f1816..af9ab59c 100644 --- a/src/pages/shop/brands.js +++ b/src/pages/shop/brands.js @@ -47,7 +47,7 @@ export default function Brands({ initialManufactures }) { <h1>Semua Brand di Indoteknik</h1> <div className="flex overflow-x-auto gap-x-2 py-2"> {alphabets.map((alphabet, index) => ( - <button key={index} className={"p-2 py-1 border bg-white border-gray-300 rounded w-10 flex-shrink-0" + (manufactureStartwith == alphabet ? ' bg-yellow-900 border-yellow-900 ' : '')} onClick={() => filterManufactureStartWith(alphabet)}> + <button key={index} className={"p-2 py-1 border bg-white border-gray_r-6 rounded w-10 flex-shrink-0" + (manufactureStartwith == alphabet ? ' bg-yellow_r-9 border-yellow_r-9 ' : '')} onClick={() => filterManufactureStartWith(alphabet)}> {alphabet} </button> ))} diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js index 06ac94b4..0baaccd1 100644 --- a/src/pages/shop/cart.js +++ b/src/pages/shop/cart.js @@ -10,15 +10,21 @@ import TrashIcon from "../../icons/trash.svg"; import { LazyLoadImage } from "react-lazy-load-image-component"; import apiOdoo from "../../helpers/apiOdoo"; import currencyFormat from "../../helpers/currencyFormat"; +import { createSlug } from "../../helpers/slug"; +import ConfirmAlert from "../../components/ConfirmAlert"; +import { toast } from "react-hot-toast"; 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 [deleteConfirmation, setDeleteConfirmation] = useState({ + productId: null, + show: false + }); const getProducts = async () => { let cart = getCart(); @@ -91,12 +97,29 @@ export default function Cart() { updateCart(productId, quantity); } - const deleteItem = (productId) => { + const showDeleteConfirmation = (productId) => { + setDeleteConfirmation({ + productId: productId, + show: true + }); + } + + const hideDeleteConfirmation = () => { + setDeleteConfirmation({ + productId: null, + show: false + }); + } + + const deleteItem = () => { + const productId = deleteConfirmation.productId; let productIndexToUpdate = products.findIndex((product) => product.id == productId); let productsToUpdate = products; productsToUpdate.splice(productIndexToUpdate, 1); setProducts([...productsToUpdate]); deleteItemCart(productId); + hideDeleteConfirmation(); + toast.success('Berhasil menghapus 1 item dari keranjang', { duration: 1500 }); } const toggleProductToProcess = (productId) => { @@ -108,8 +131,15 @@ export default function Cart() { return ( <> + <ConfirmAlert + title="Apakah anda yakin menghapus item dari keranjang?" + show={deleteConfirmation.show} + onClose={hideDeleteConfirmation} + onSubmit={deleteItem} + /> <Header title={`Keranjang Belanja - Indoteknik`}/> <Layout> + {/* 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"> @@ -154,9 +184,12 @@ export default function Cart() { </div> <div className="w-8/12 flex flex-col"> <Link href={'/shop/product/' + createSlug(product.parent.name, product.parent.id)} className="product-card__title wrap-line-ellipsis-2"> - {product.parent.name} {product.attributes.length > 0 ? `- ${product.attributes.join(', ')}` : ''} + {product.parent.name} </Link> - <p className="text-caption-1 text-gray_r-11 mt-1">{product.code ? product.code : '-'}</p> + <p className="text-caption-1 text-gray_r-11 mt-1"> + {product.code || '-'} + {product.attributes.length > 0 ? ` | ${product.attributes.join(', ')}` : ''} + </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 ? ( @@ -169,15 +202,15 @@ export default function Cart() { </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"> + <div className="flex gap-x-2 items-center"> <button - className="btn-red p-1 rounded" - onClick={() => deleteItem(product.id)} + className="btn-red p-2 rounded" + onClick={() => showDeleteConfirmation(product.id)} > <TrashIcon className="stroke-red_r-12 w-3"/> </button> <button - className="btn-light p-1 rounded" + className="btn-light p-2 rounded" disabled={product.quantity == 1} onClick={() => minusQuantity(product.id)} > @@ -190,7 +223,7 @@ export default function Cart() { onChange={(e) => updateQuantity(product.id, e.target.value)} value={product.quantity} /> - <button className="btn-light p-1 rounded" onClick={() => plusQuantity(product.id)}> + <button className="btn-light p-2 rounded" onClick={() => plusQuantity(product.id)}> <PlusIcon className="stroke-gray_r-12 w-3"/> </button> </div> @@ -207,7 +240,7 @@ export default function Cart() { <div className="flex justify-between items-center"> <h2>Ringkasan Pesanan</h2> {getProductsToProcess().length > 0 ? ( - <p className="text-gray_r-11">{getProductsToProcess().length} Barang</p> + <p className="text-gray_r-11 text-caption-1">{getProductsToProcess().length} Barang</p> ) : ''} </div> <hr className="my-4 border-gray_r-6"/> diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js index 9bb76fb6..de52eb72 100644 --- a/src/pages/shop/product/[slug].js +++ b/src/pages/shop/product/[slug].js @@ -10,6 +10,7 @@ import "react-lazy-load-image-component/src/effects/blur.css"; import ProductSlider from "../../../components/product/ProductSlider"; import Layout from "../../../components/Layout"; import { createOrUpdateItemCart } from "../../../helpers/cart"; +import toast from "react-hot-toast"; export async function getServerSideProps( context ) { const { slug } = context.query; @@ -83,6 +84,7 @@ export default function ProductDetail({ product }) { let addItemToCart = () => { if (quantity > 0) { + toast.success('Berhasil menambahkan ke keranjang', { duration: 1500 }); createOrUpdateItemCart(activeVariant.id, parseInt(quantity)); } return true; @@ -143,7 +145,7 @@ export default function ProductDetail({ product }) { <button className="btn-yellow w-full" onClick={addItemToCart} - disabled={(product.lowest_price.price == 0 ? true : false)} + disabled={(product.lowest_price.price == 0 ? true : false) || (product.variant_total > 1 && !selectedVariant)} > + Keranjang </button> diff --git a/src/styles/globals.css b/src/styles/globals.css index d3fb5643..b10e043a 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -65,28 +65,28 @@ html, body { .badge-red { @apply - bg-red_r-6 + bg-red_r-5 text-red_r-11 ; } .badge-gray { @apply - bg-gray_r-6 + bg-gray_r-5 text-gray_r-11 ; } .badge-yellow { @apply - bg-yellow_r-6 + bg-yellow_r-5 text-yellow_r-11 ; } .badge-green { @apply - bg-green_r-6 + bg-green_r-5 text-green_r-11 ; } @@ -261,7 +261,7 @@ html, body { w-full h-full z-[55] - bg-gray-900/60 + bg-gray_r-12/60 ; } |
