diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-31 14:32:38 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-31 14:32:38 +0700 |
| commit | 3496025d97140268dc2e899adca994b5b9f343c0 (patch) | |
| tree | 3d8b51fc624b09a7ba46409e9e8a81fbd02da582 /src/pages/shop | |
| parent | d194dcc23c19a4cf31863b32770f8df77e1f675a (diff) | |
quotation and categories
Diffstat (limited to 'src/pages/shop')
| -rw-r--r-- | src/pages/shop/cart.js | 1 | ||||
| -rw-r--r-- | src/pages/shop/checkout.js | 1 | ||||
| -rw-r--r-- | src/pages/shop/product/[slug].js | 2 | ||||
| -rw-r--r-- | src/pages/shop/quotation/finish.js | 39 | ||||
| -rw-r--r-- | src/pages/shop/quotation/index.js | 142 | ||||
| -rw-r--r-- | src/pages/shop/search.js | 4 |
6 files changed, 185 insertions, 4 deletions
diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js index 53d5e648..aaf67e1f 100644 --- a/src/pages/shop/cart.js +++ b/src/pages/shop/cart.js @@ -276,6 +276,7 @@ export default function Cart() { <button className="flex-1 btn-light" disabled={getProductsSelected().length == 0} + onClick={() => router.push('/shop/quotation')} > Quotation {getProductsSelected().length > 0 && `(${getProductsSelected().length})`} </button> diff --git a/src/pages/shop/checkout.js b/src/pages/shop/checkout.js index 49d1a848..f55b200f 100644 --- a/src/pages/shop/checkout.js +++ b/src/pages/shop/checkout.js @@ -2,7 +2,6 @@ import { ExclamationCircleIcon } from "@heroicons/react/24/solid"; import { useEffect, useState } from "react"; import Alert from "@/components/elements/Alert"; import AppBar from "@/components/layouts/AppBar"; -import Image from "@/components/elements/Image"; import Layout from "@/components/layouts/Layout"; import LineDivider from "@/components/elements/LineDivider"; import Link from "@/components/elements/Link"; diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js index dd097bbe..bcfb12ba 100644 --- a/src/pages/shop/product/[slug].js +++ b/src/pages/shop/product/[slug].js @@ -149,7 +149,7 @@ export default function ProductDetail({ product }) { /> <div className="p-4"> - <div className="flex justify-between"> + <div className="flex justify-between gap-x-3"> <div> <Link href={'/shop/brands/' + createSlug(product.manufacture.name, product.manufacture.id)}> {product.manufacture.name ?? '-'} diff --git a/src/pages/shop/quotation/finish.js b/src/pages/shop/quotation/finish.js new file mode 100644 index 00000000..b1f092d3 --- /dev/null +++ b/src/pages/shop/quotation/finish.js @@ -0,0 +1,39 @@ +import WithAuth from "@/components/auth/WithAuth"; +import Link from "@/components/elements/Link"; +import Header from "@/components/layouts/Header"; +import Layout from "@/components/layouts/Layout"; +import { useAuth } from "@/core/utils/auth"; +import { EnvelopeIcon } from "@heroicons/react/24/outline"; +import { useRouter } from "next/router"; + +export default function FinishQuotation() { + const router = useRouter(); + const { id } = router.query; + const [ auth ] = useAuth(); + + return ( + <WithAuth> + <Layout> + <Header title="Penawaran Harga" /> + + <div className="m-4 px-4 py-6 shadow-md border border-gray_r-3"> + <div className="flex"> + <span className="p-3 mx-auto bg-yellow_r-3 border border-yellow_r-6 rounded"> + <EnvelopeIcon className="w-8 text-yellow_r-11" /> + </span> + </div> + <p className="h2 text-center mt-6"> + Terima Kasih { auth?.name } + </p> + <p className="text-center mt-3 leading-6 text-gray_r-11"> + Penawaran harga kamu di Indoteknik.com berhasil dikirimkan, tim kami akan segera menghubungi anda. + </p> + { id && ( + <Link href={`/my/transaction/${id}`} className="btn-yellow text-gray_r-12 mt-6 w-full">Lihat Penawaran</Link> + )} + <Link href="/" className="btn-light text-gray_r-12 mt-4 w-full">Ke Halaman Utama</Link> + </div> + </Layout> + </WithAuth> + ); +}
\ No newline at end of file diff --git a/src/pages/shop/quotation/index.js b/src/pages/shop/quotation/index.js new file mode 100644 index 00000000..cf2b956d --- /dev/null +++ b/src/pages/shop/quotation/index.js @@ -0,0 +1,142 @@ +import WithAuth from "@/components/auth/WithAuth"; +import LineDivider from "@/components/elements/LineDivider"; +import Link from "@/components/elements/Link"; +import AppBar from "@/components/layouts/AppBar"; +import Layout from "@/components/layouts/Layout"; +import VariantCard from "@/components/variants/VariantCard"; +import apiOdoo from "@/core/utils/apiOdoo"; +import { useAuth } from "@/core/utils/auth"; +import { deleteItemCart, getCart } from "@/core/utils/cart"; +import currencyFormat from "@/core/utils/currencyFormat"; +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import { toast } from "react-hot-toast"; + +export default function Quotation() { + const router = useRouter(); + const [ auth ] = useAuth(); + const [ products, setProducts ] = useState([]); + const [ totalPriceBeforeTax, setTotalPriceBeforeTax ] = useState(0); + const [ totalTaxAmount, setTotalTaxAmount ] = useState(0); + const [ totalDiscountAmount, setTotalDiscountAmount ] = useState(0); + + useEffect(() => { + const getProducts = async () => { + let cart = getCart(); + let productIds = Object + .values(cart) + .filter((itemCart) => itemCart.selected == true) + .map((itemCart) => itemCart.product_id); + 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, + selected: cart[product.id].selected, + })); + setProducts(dataProducts); + } + }; + getProducts(); + }, [ router, auth ]); + + useEffect(() => { + if (products) { + const productsSelected = products.filter((product) => product.selected == true); + let calculateTotalPriceBeforeTax = 0; + let calculateTotalTaxAmount = 0; + let calculateTotalDiscountAmount = 0; + productsSelected.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 submitQuotation = async () => { + let productOrder = products.map((product) => ({ 'product_id': product.id, 'quantity': product.quantity })); + let data = { + 'partner_shipping_id': auth.partner_id, + 'partner_invoice_id': auth.partner_id, + 'order_line': JSON.stringify(productOrder) + }; + const quotation = await apiOdoo('POST', `/api/v1/partner/${auth.partner_id}/sale_order/checkout`, data); + for (const product of products) { + deleteItemCart(product.id); + } + if (quotation?.id) { + router.push(`/shop/quotation/finish?id=${quotation.id}`); + return; + }; + toast.error('Terdapat kesalahan internal, hubungi kami'); + } + return ( + <WithAuth> + <Layout> + <AppBar title="Penawaran Harga" /> + + <div className="p-4 flex flex-col gap-y-4"> + <p className="h2">Produk</p> + {products.map((product, index) => ( + <VariantCard + data={product} + openOnClick={false} + key={index} + /> + ))} + </div> + + <LineDivider /> + + <div className="p-4"> + <div className="flex justify-between items-center"> + <p className="h2">Ringkasan Penawaran</p> + <p className="text-gray_r-11 text-caption-1">{products.length} Barang</p> + </div> + <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>Subtotal</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>Grand Total</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> + + <LineDivider /> + + <div className="p-4"> + <button + type="button" + className="btn-yellow w-full" + onClick={submitQuotation} + > + Kirim Penawaran + </button> + </div> + </Layout> + </WithAuth> + ) +}
\ No newline at end of file diff --git a/src/pages/shop/search.js b/src/pages/shop/search.js index 2521c7a2..4152bd43 100644 --- a/src/pages/shop/search.js +++ b/src/pages/shop/search.js @@ -10,7 +10,7 @@ import Footer from "@/components/layouts/Footer"; export async function getServerSideProps(context) { const { - q, + q = '*', page = 1, brand = '', category = '', @@ -100,7 +100,7 @@ export default function ShopSearch({ </> ) : ''} {searchResults.response.numFound} - produk untuk pencarian <span className="font-semibold">{q}</span> + produk { q != '*' && (<>untuk pencarian <span className="font-semibold">{q}</span></>) } </> ) : 'Mungkin yang anda cari'} </div> |
