diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-10 05:38:03 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-10 05:38:03 +0700 |
| commit | 3770bcca65e85af7273a3f565b3ca616f852e936 (patch) | |
| tree | a3b3480e2c37a7aa746b6e0d74e3399d76be8838 /src | |
| parent | 3b4d6bf4f389cbb680e4bd5a0776e31d058b4195 (diff) | |
optimize cart code
Diffstat (limited to 'src')
| -rw-r--r-- | src/pages/shop/cart.js | 246 |
1 files changed, 130 insertions, 116 deletions
diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js index e480d117..cdb79178 100644 --- a/src/pages/shop/cart.js +++ b/src/pages/shop/cart.js @@ -42,7 +42,6 @@ export default function Cart() { show: false }); - useEffect(() => { const getProducts = async () => { let cart = getCart(); @@ -150,6 +149,129 @@ export default function Cart() { setProducts([...productsToUpdate]); } + // Components + const CartEmpty = () => ( + <div className="text-center mt-14"> + <ExclamationTriangleIcon className="w-12 mx-auto"/> + <p className="mt-2 h2">Keranjang belanja anda masih kosong.</p> + <Link href="/" className="btn-yellow text-gray_r-12 mx-auto mt-4">Mulai Belanja</Link> + </div> + ); + + const CartLoader = () => ( + <div className="flex justify-center items-center gap-x-3 mt-14"> + <Spinner className="w-10 text-gray_r-8 fill-gray_r-12" /> + </div> + ); + + const CartWarningAlert = () => { + <div className="p-4"> + <Alert type="warning" className="text-caption-2 flex gap-x-3 items-center"> + <div> + <ExclamationCircleIcon className="w-8 text-yellow_r-11"/> + </div> + <span>Mohon dicek kembali & pastikan pesanan kamu sudah sesuai dengan yang kamu butuhkan. Atau bisa hubungi kami.</span> + </Alert> + </div> + }; + + const CartProductList = () => ( + <div className="p-4 flex flex-col gap-y-6"> + <div className="flex justify-between items-center"> + <h2>Daftar Produk Belanja</h2> + <Link href="/" className="text-caption-1">Cari Produk Lain</Link> + </div> + {products.map((product, index) => ( + <div className="flex gap-x-3" key={index}> + <div className="w-4/12 flex items-center gap-x-2" onClick={() => toggleProductSelected(product.id)}> + <button + className={'p-2 rounded border-2 ' + (product.selected ? 'border-yellow_r-9 bg-yellow_r-9' : 'border-gray_r-12')} + ></button> + <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> + <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} + </Link> + <p className="text-caption-2 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-2 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-2 text-gray_r-12 font-bold">{currencyFormat(product.quantity * product.price.price_discount)}</p> + <div className="flex gap-x-2 items-center"> + <button + className="btn-red p-2 rounded" + onClick={() => showDeleteConfirmation(product.id)} + > + <TrashIcon className="text-red_r-11 w-3"/> + </button> + <button + className="btn-light p-2 rounded" + disabled={product.quantity == 1} + onClick={() => minusQuantity(product.id)} + > + <MinusIcon className={'text-gray_r-12 w-3' + (product.quantity == 1 ? ' text-gray_r-11' : '')}/> + </button> + <input + type="number" + 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-2 rounded" onClick={() => plusQuantity(product.id)}> + <PlusIcon className="text-gray_r-12 w-3"/> + </button> + </div> + </div> + </div> + </div> + ))} + </div> + ); + + const ActionButton = () => ( + <div className="p-4 bg-gray_r-1 sticky bottom-0 border-t-4 border-gray_r-4"> + <div className="flex"> + <p>Total</p> + <p className="text-gray_r-11 ml-1">{getProductsSelected().length > 0 && ( + <>({ getProductsSelected().length } Barang)</> + )}</p> + <p className="font-semibold text-red_r-11 ml-auto">{currencyFormat(totalPriceBeforeTax + totalTaxAmount - totalDiscountAmount)}</p> + </div> + + <div className="flex gap-x-3 mt-4"> + <button + className="flex-1 btn-light" + disabled={getProductsSelected().length == 0} + > + Quotation {getProductsSelected().length > 0 && `(${getProductsSelected().length})`} + </button> + <button + className="flex-1 btn-yellow" + disabled={getProductsSelected().length == 0} + onClick={() => router.push('/shop/checkout')} + > + Checkout {getProductsSelected().length > 0 && `(${getProductsSelected().length})`} + </button> + </div> + </div> + ); + return ( <> <ConfirmAlert @@ -163,19 +285,9 @@ export default function Cart() { <Layout> <AppBar title="Keranjang Saya" /> - {isLoadingProducts && ( - <div className="flex justify-center items-center gap-x-3 mt-14"> - <Spinner className="w-10 text-gray_r-8 fill-gray_r-12" /> - </div> - )} + {isLoadingProducts && <CartLoader /> } - { !isLoadingProducts && products.length == 0 && ( - <div className="text-center mt-14"> - <ExclamationTriangleIcon className="w-12 mx-auto"/> - <p className="mt-2 h2">Keranjang belanja anda masih kosong.</p> - <Link href="/" className="btn-yellow text-gray_r-12 mx-auto mt-4">Mulai Belanja</Link> - </div> - ) } + { !isLoadingProducts && products.length == 0 && <CartEmpty /> } { !isLoadingProducts && products.length > 0 && ( <> @@ -184,113 +296,15 @@ export default function Cart() { labels={['Keranjang', 'Pembayaran', 'Selesai']} /> - <LineDivider/> + <LineDivider /> - {/* --- Start Alert */} - <div className="p-4"> - <Alert type="warning" className="text-caption-2 flex gap-x-3 items-center"> - <div> - <ExclamationCircleIcon className="w-8 text-yellow_r-11"/> - </div> - <span>Mohon dicek kembali & pastikan pesanan kamu sudah sesuai dengan yang kamu butuhkan. Atau bisa hubungi kami.</span> - </Alert> - </div> - {/* ---- End Alert */} + <CartWarningAlert /> - <LineDivider/> + <LineDivider /> - <div className="p-4 flex flex-col gap-y-6"> - <div className="flex justify-between items-center"> - <h2>Daftar Produk Belanja</h2> - <Link href="/" className="text-caption-1">Cari Produk Lain</Link> - </div> - {products.map((product, index) => ( - <div className="flex gap-x-3" key={index}> - <div className="w-4/12 flex items-center gap-x-2" onClick={() => toggleProductSelected(product.id)}> - <button - className={'p-2 rounded border-2 ' + (product.selected ? 'border-yellow_r-9 bg-yellow_r-9' : 'border-gray_r-12')} - ></button> - <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> - <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} - </Link> - <p className="text-caption-2 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-2 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-2 text-gray_r-12 font-bold">{currencyFormat(product.quantity * product.price.price_discount)}</p> - <div className="flex gap-x-2 items-center"> - <button - className="btn-red p-2 rounded" - onClick={() => showDeleteConfirmation(product.id)} - > - <TrashIcon className="text-red_r-11 w-3"/> - </button> - <button - className="btn-light p-2 rounded" - disabled={product.quantity == 1} - onClick={() => minusQuantity(product.id)} - > - <MinusIcon className={'text-gray_r-12 w-3' + (product.quantity == 1 ? ' text-gray_r-11' : '')}/> - </button> - <input - type="number" - 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-2 rounded" onClick={() => plusQuantity(product.id)}> - <PlusIcon className="text-gray_r-12 w-3"/> - </button> - </div> - </div> - </div> - </div> - ))} - </div> + <CartProductList /> - <div className="p-4 bg-gray_r-1 sticky bottom-0 border-t-4 border-gray_r-4"> - <div className="flex"> - <p>Total</p> - <p className="text-gray_r-11 ml-1">{getProductsSelected().length > 0 && ( - <>({ getProductsSelected().length } Barang)</> - )}</p> - <p className="font-semibold text-red_r-11 ml-auto">{currencyFormat(totalPriceBeforeTax + totalTaxAmount - totalDiscountAmount)}</p> - </div> - - <div className="flex gap-x-3 mt-4"> - <button - className="flex-1 btn-light" - disabled={getProductsSelected().length == 0} - > - Quotation {getProductsSelected().length > 0 && `(${getProductsSelected().length})`} - </button> - <button - className="flex-1 btn-yellow" - disabled={getProductsSelected().length == 0} - onClick={() => router.push('/shop/checkout')} - > - Checkout {getProductsSelected().length > 0 && `(${getProductsSelected().length})`} - </button> - </div> - </div> + <ActionButton /> </> ) } </Layout> |
