diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-09 12:08:27 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-09 12:08:27 +0700 |
| commit | bd1e930f875e942ee8a60718a3c1268a62598266 (patch) | |
| tree | 6c6ca1d56fd257b33425c25fe2aa75623bddcbe9 /src/pages | |
| parent | db76cfe50ea485333f9aab8e3580ac7b352350ed (diff) | |
checkout to odoo, select address
Diffstat (limited to 'src/pages')
| -rw-r--r-- | src/pages/my/address/index.js | 28 | ||||
| -rw-r--r-- | src/pages/shop/cart.js | 14 | ||||
| -rw-r--r-- | src/pages/shop/checkout.js | 362 |
3 files changed, 254 insertions, 150 deletions
diff --git a/src/pages/my/address/index.js b/src/pages/my/address/index.js index cac6e8f6..b97e21e7 100644 --- a/src/pages/my/address/index.js +++ b/src/pages/my/address/index.js @@ -5,10 +5,15 @@ import Link from "../../../components/Link"; import WithAuth from "../../../components/WithAuth"; import apiOdoo from "../../../helpers/apiOdoo"; import { useAuth } from "../../../helpers/auth"; +import { useRouter } from "next/router"; +import { createOrUpdateItemAddress, getItemAddress } from "../../../helpers/address"; export default function Address() { - const [auth] = useAuth(); - const [addresses, setAddresses] = useState(null); + const router = useRouter(); + const { select } = router.query; + const [ auth ] = useAuth(); + const [ addresses, setAddresses ] = useState(null); + const [ selectedAdress, setSelectedAdress ] = useState(null); useEffect(() => { const getAddress = async () => { @@ -20,6 +25,19 @@ export default function Address() { getAddress(); }, [auth]); + useEffect(() => { + if (select) { + setSelectedAdress(getItemAddress(select)); + } + }, [select]); + + const changeSelectedAddress = (id) => { + if (select) { + createOrUpdateItemAddress(select, id); + router.back(); + } + }; + return ( <WithAuth> <Layout> @@ -31,7 +49,11 @@ export default function Address() { <div className="grid gap-y-4 p-4"> { addresses && addresses.map((address, index) => ( - <div className="p-4 rounded-md border border-gray_r-7" key={index}> + <div + key={index} + className={"p-4 rounded-md border " + (selectedAdress && selectedAdress == address.id ? "border-yellow_r-7 bg-yellow_r-2" : "border-gray_r-7") } + onClick={() => changeSelectedAddress(address.id)} + > <p className="font-medium">{ address.name }</p> <p className="mt-3 text-gray_r-11">{ address.mobile }</p> <p className="mt-1 text-gray_r-11 leading-6">{ address.street } { address.street2 }</p> diff --git a/src/pages/shop/cart.js b/src/pages/shop/cart.js index eb295c1f..e480d117 100644 --- a/src/pages/shop/cart.js +++ b/src/pages/shop/cart.js @@ -187,12 +187,14 @@ export default function Cart() { <LineDivider/> {/* --- Start Alert */} - <Alert type="warning" className="text-caption-2 flex gap-x-3 items-center my-2"> - <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 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 */} <LineDivider/> diff --git a/src/pages/shop/checkout.js b/src/pages/shop/checkout.js index 54b9d598..a72b8976 100644 --- a/src/pages/shop/checkout.js +++ b/src/pages/shop/checkout.js @@ -1,6 +1,5 @@ import { ExclamationCircleIcon } from "@heroicons/react/24/solid"; import { useEffect, useState } from "react"; -import { toast } from "react-hot-toast"; import Alert from "../../components/Alert"; import AppBar from "../../components/AppBar"; import Image from "../../components/Image"; @@ -11,21 +10,28 @@ import ProgressBar from "../../components/ProgressBar"; import Spinner from "../../components/Spinner"; import apiOdoo from "../../helpers/apiOdoo"; import { useAuth } from "../../helpers/auth"; -import { getCart } from "../../helpers/cart"; +import { deleteItemCart, getCart } from "../../helpers/cart"; import currencyFormat from "../../helpers/currencyFormat"; -import { createSlug } from "../../helpers/slug"; - +import { getItemAddress } from "../../helpers/address"; +import { useRouter } from "next/router"; +import WithAuth from "../../components/WithAuth"; +import { toast } from "react-hot-toast"; export default function Checkout() { + const router = useRouter(); const [auth] = useAuth(); - const [address, setAddress] = useState(null); - const [selectedAddress, setSelectedAddress] = useState(null); + const [addresses, setAddresses] = useState(null); + const [selectedAddress, setSelectedAddress] = useState({ + shipping: null, + invoicing: null + }); const [selectedPayment, setSelectedPayment] = useState(null); const [products, setProducts] = useState(null); const [totalPriceBeforeTax, setTotalPriceBeforeTax] = useState(0); const [totalTaxAmount, setTotalTaxAmount] = useState(0); const [totalDiscountAmount, setTotalDiscountAmount] = useState(0); const [isLoading, setIsLoading] = useState(true); + const [finishCheckout, setFinishCheckout] = useState(null); const payments = [ { name: 'BCA', number: '8870-4000-81' }, @@ -33,13 +39,13 @@ export default function Checkout() { ]; useEffect(() => { - const getAddress = async () => { + const getAddresses = async () => { if (auth) { - const dataAddress = await apiOdoo('GET', `/api/v1/user/${auth.id}/address`); - setAddress(dataAddress); + const dataAddresses = await apiOdoo('GET', `/api/v1/user/${auth.id}/address`); + setAddresses(dataAddresses); } }; - getAddress(); + getAddresses(); }, [auth]); useEffect(() => { @@ -58,14 +64,29 @@ export default function Checkout() { selected: cart[product.id].selected, })); setProducts(dataProducts); + } else { + if (auth) router.push('/shop/cart'); } }; getProducts(); - }, []); + }, [router, auth]); useEffect(() => { - if (address) setSelectedAddress(address[0]); - }, [address]); + if (addresses) { + const matchAddress = (key) => { + const addressToMatch = getItemAddress(key); + let foundAddress = addresses.filter((address) => address.id == addressToMatch); + if (foundAddress.length > 0) { + return foundAddress[0]; + } + return addresses[0]; + } + setSelectedAddress({ + shipping: matchAddress('shipping'), + invoicing: matchAddress('invoicing'), + }); + }; + }, [addresses]); useEffect(() => { if (products) { @@ -86,147 +107,206 @@ export default function Checkout() { }, [products]); useEffect(() => { - if (address && products) setIsLoading(false); - }, [address, products]); + if (addresses && products) setIsLoading(false); + }, [addresses, products]); + + const submit = async () => { + if (!selectedPayment) { + toast.error('Mohon pilih metode pembayaran terlebih dahulu', { + position: 'bottom-center' + }); + return; + } + let productOrder = products.map((product) => ({ 'product_id': product.id, 'quantity': product.quantity })); + let data = { + 'user_id': auth.id, + 'partner_id': auth.partner_id, + 'partner_shipping_id': selectedAddress.shipping.id, + 'partner_invoice_id': selectedAddress.invoicing.id, + 'order_line': JSON.stringify(productOrder) + } + const checkoutToOdoo = await apiOdoo('POST', '/api/v1/sale_order/checkout', data); + for (const product of products) { + deleteItemCart(product.id); + } + setFinishCheckout(checkoutToOdoo); + } return ( - <Layout> - <AppBar title="Checkout" /> - - {isLoading && ( - <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> - )} - - { products && address && ( - <> - <ProgressBar - current={2} - labels={['Keranjang', 'Pembayaran', 'Selesai']} - /> - - <LineDivider/> - - <Alert type="info" className="text-caption-2 flex gap-x-3 items-center my-2"> - <div> - <ExclamationCircleIcon className="w-6 text-blue-700"/> + <WithAuth> + <Layout> + <AppBar title={finishCheckout ? "Pembelian Berhasil" : "Checkout"} /> + + { finishCheckout ? ( + <div className="m-4 rounded-xl bg-yellow_r-4 text-center border border-yellow_r-7"> + <div className="px-4 py-6"> + <p className="h2 mb-2">Terima Kasih atas Pembelian Anda</p> + <p className="text-gray_r-11 mb-4">Details pembelian sudah kami kirimkan melalui email anda. Mohon dicek kembali. jika tidak menerima email anda dapat menghubungi kami disini.</p> + <p className="mb-2 font-medium">{ finishCheckout.name }</p> + <p className="text-caption-2 text-gray_r-11">No. Transaksi</p> </div> - <span>Jika mengalami kesulitan dalam melakukan pembelian di website Indoteknik. Hubungi kami disini</span> - </Alert> + <div className="bg-yellow_r-6 rounded-b-xl py-4"> + Mohon konfirmasi pembelian Anda disini + </div> + </div> + ) : ( + <> + {isLoading && ( + <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> + )} - <LineDivider/> + { products && addresses && ( + <> + <ProgressBar + current={2} + labels={['Keranjang', 'Pembayaran', 'Selesai']} + /> - <div className="p-4"> - <div className="flex justify-between items-center"> - <h2>Alamat Pengiriman</h2> - <Link className="text-caption-1" href="/">Ubah Alamat</Link> - </div> + <LineDivider/> - { selectedAddress && ( - <div className="mt-4 text-caption-1"> - <p className="font-medium">{ selectedAddress.name }</p> - <p className="mt-2 text-gray_r-11">{ selectedAddress.mobile }</p> - <p className="mt-1 text-gray_r-11">{ selectedAddress.street } { selectedAddress.street2 }</p> - </div> - ) } - </div> + <div className="p-4"> + <Alert type="info" className="text-caption-2 flex gap-x-3 items-center"> + <div> + <ExclamationCircleIcon className="w-6 text-blue-700"/> + </div> + <span>Jika mengalami kesulitan dalam melakukan pembelian di website Indoteknik. Hubungi kami disini</span> + </Alert> + </div> + + <LineDivider/> - <LineDivider/> - - <div className="p-4 flex flex-col gap-y-4"> - {products.map((product, index) => ( - <div className="flex gap-x-3" key={index}> - <div className="w-4/12 flex items-center gap-x-2"> - <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 className="p-4"> + <div className="flex justify-between items-center"> + <h2>Alamat Pengiriman</h2> + <Link className="text-caption-1" href="/my/address?select=shipping">Pilih Alamat Lain</Link> + </div> + + { selectedAddress.shipping && ( + <div className="mt-4 text-caption-1"> + <p className="font-medium">{ selectedAddress.shipping.name }</p> + <p className="mt-2 text-gray_r-11">{ selectedAddress.shipping.mobile }</p> + <p className="mt-1 text-gray_r-11">{ selectedAddress.shipping.street } { selectedAddress.shipping.street2 }</p> + </div> + ) } </div> - <div className="w-8/12 flex flex-col"> - <p className="product-card__title wrap-line-ellipsis-2"> - {product.parent.name} - </p> - <p className="text-caption-2 text-gray_r-11 mt-1"> - {product.code || '-'} - {product.attributes.length > 0 ? ` | ${product.attributes.join(', ')}` : ''} - </p> - <p className="text-caption-2 text-gray_r-11 mt-1"> - {currencyFormat(product.price.price_discount)} × {product.quantity} Barang - </p> - <p className="text-caption-2 text-gray_r-12 font-bold mt-2"> - {currencyFormat(product.quantity * product.price.price_discount)} + + <LineDivider/> + + <div className="p-4 flex flex-col gap-y-4"> + {products.map((product, index) => ( + <div className="flex gap-x-3" key={index}> + <div className="w-4/12 flex items-center gap-x-2"> + <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"> + <p className="product-card__title wrap-line-ellipsis-2"> + {product.parent.name} + </p> + <p className="text-caption-2 text-gray_r-11 mt-1"> + {product.code || '-'} + {product.attributes.length > 0 ? ` | ${product.attributes.join(', ')}` : ''} + </p> + <p className="text-caption-2 text-gray_r-11 mt-1"> + {currencyFormat(product.price.price_discount)} × {product.quantity} Barang + </p> + <p className="text-caption-2 text-gray_r-12 font-bold mt-2"> + {currencyFormat(product.quantity * product.price.price_discount)} + </p> + </div> + </div> + ))} + </div> + + <LineDivider/> + + <div className="p-4"> + <div className="flex justify-between items-center"> + <h2>Ringkasan Pesanan</h2> + <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> - </div> - ))} - </div> - <LineDivider/> - - <div className="p-4"> - <div className="flex justify-between items-center"> - <h2>Ringkasan Pesanan</h2> - <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/> - <LineDivider/> - - <div className="p-4"> - <h2>Pilih Metode Pembayaran</h2> - <div className="grid gap-y-3 mt-4"> - { payments.map((payment, index) => ( - <button - type="button" - className={"text-left border border-gray_r-6 rounded-md p-3 " + (selectedPayment == payment.name && 'border-yellow_r-10 bg-yellow_r-3')} - onClick={() => setSelectedPayment(payment.name)} - key={index} - > - <p>{payment.name} - {payment.number}</p> - <p className="mt-1 text-gray_r-11">PT. Indoteknik Dotcom Gemilang</p> - </button> - )) } - </div> - </div> + <div className="p-4"> + <div className="flex justify-between items-center"> + <h2>Alamat Penagihan</h2> + <Link className="text-caption-1" href="/my/address?select=invoicing">Pilih Alamat Lain</Link> + </div> - <LineDivider/> + { selectedAddress.invoicing && ( + <div className="mt-4 text-caption-1"> + <p className="font-medium">{ selectedAddress.invoicing.name }</p> + <p className="mt-2 text-gray_r-11">{ selectedAddress.invoicing.mobile }</p> + <p className="mt-1 text-gray_r-11">{ selectedAddress.invoicing.street } { selectedAddress.invoicing.street2 }</p> + </div> + ) } + </div> - <div className="flex gap-x-3 p-4"> - <button - className="flex-1 btn-yellow" - onClick={() => router.push('/shop/checkout')} - > - Bayar - </button> - </div> - </> - ) } - </Layout> + <LineDivider/> + + <div className="p-4"> + <h2>Pilih Metode Pembayaran</h2> + <div className="grid gap-y-3 mt-4"> + { payments.map((payment, index) => ( + <button + type="button" + className={"text-left border border-gray_r-6 rounded-md p-3 " + (selectedPayment == payment.name && 'border-yellow_r-10 bg-yellow_r-3')} + onClick={() => setSelectedPayment(payment.name)} + key={index} + > + <p>{payment.name} - {payment.number}</p> + <p className="mt-1 text-gray_r-11">PT. Indoteknik Dotcom Gemilang</p> + </button> + )) } + </div> + </div> + + <LineDivider/> + + <div className="flex gap-x-3 p-4"> + <button + className="flex-1 btn-yellow" + onClick={submit} + > + Bayar + </button> + </div> + </> + ) } + </> + ) } + </Layout> + </WithAuth> ) }
\ No newline at end of file |
