diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/checkout/api/ExpedisiList.js | 8 | ||||
| -rw-r--r-- | src/lib/checkout/api/serviceExpedisi.js | 8 | ||||
| -rw-r--r-- | src/lib/checkout/components/Checkout.jsx | 308 | ||||
| -rw-r--r-- | src/lib/variant/components/VariantCard.jsx | 3 |
4 files changed, 318 insertions, 9 deletions
diff --git a/src/lib/checkout/api/ExpedisiList.js b/src/lib/checkout/api/ExpedisiList.js new file mode 100644 index 00000000..ca22bec1 --- /dev/null +++ b/src/lib/checkout/api/ExpedisiList.js @@ -0,0 +1,8 @@ +import odooApi from '@/core/api/odooApi' + +const ExpedisiList = async () => { + const dataExpedisi = await odooApi('GET', '/api/v1/courier') + return dataExpedisi +} + +export default ExpedisiList diff --git a/src/lib/checkout/api/serviceExpedisi.js b/src/lib/checkout/api/serviceExpedisi.js new file mode 100644 index 00000000..0ff0aa03 --- /dev/null +++ b/src/lib/checkout/api/serviceExpedisi.js @@ -0,0 +1,8 @@ +import rajaOngkir from '@/core/api/rajaOngkirApi' + +const serviceExpedisi = async (body) => { + const dataExpedisi = await rajaOngkir('POST', '/starter/cost', body) + return dataExpedisi +} + +export default serviceExpedisi diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index dc3908db..b2f9a866 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -6,7 +6,7 @@ import { getItemAddress } from '@/core/utils/address' import addressesApi from '@/lib/address/api/addressesApi' import CartApi from '@/lib/cart/api/CartApi' import { ExclamationCircleIcon } from '@heroicons/react/24/outline' -import { useEffect, useRef, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import _ from 'lodash' import { deleteItemCart, getCart, getItemCart } from '@/core/utils/cart' import currencyFormat from '@/core/utils/currencyFormat' @@ -19,8 +19,11 @@ import axios from 'axios' import Image from '@/core/components/elements/Image/Image' import MobileView from '@/core/components/views/MobileView' import DesktopView from '@/core/components/views/DesktopView' +import ExpedisiList from '../api/ExpedisiList' import whatsappUrl from '@/core/utils/whatsappUrl' import { createSlug } from '@/core/utils/slug' +import { Button, Modal } from 'flowbite-react' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' const Checkout = () => { const router = useRouter() @@ -63,7 +66,32 @@ const Checkout = () => { const [products, setProducts] = useState(null) const [totalAmount, setTotalAmount] = useState(0) const [totalDiscountAmount, setTotalDiscountAmount] = useState(0) + const [totalWeight, setTotalWeight] = useState(0) const [priceCheck, setPriceCheck] = useState(false) + const [listExpedisi, setExpedisi] = useState([]) + const [listserviceExpedisi, setListServiceExpedisi] = useState([]) + const [selectedExpedisi, setSelectedExpedisi] = useState(0) + const [selectedCarrierId, setselectedCarrierId] = useState(0) + const [selectedCarrier, setselectedCarrier] = useState(0) + const [biayaKirim, setBiayaKirim] = useState(0) + const [checkWeigth, setCheckWeight] = useState(false) + const [selectedServiceType, setSelectedServiceType] = useState(null) + const [selectedExpedisiService, setselectedExpedisiService] = useState(null) + const [etd, setEtd] = useState(null) + const [etdFix, setEtdFix] = useState(null) + + useEffect(() => { + const loadExpedisi = async () => { + let dataExpedisi = await ExpedisiList() + dataExpedisi = dataExpedisi.map((expedisi) => ({ + value: expedisi.id, + label: expedisi.name, + carrierId: expedisi.deliveryCarrierId + })) + setExpedisi(dataExpedisi) + } + loadExpedisi() + }, []) useEffect(() => { const loadProducts = async () => { @@ -97,16 +125,101 @@ const Checkout = () => { if (products) { let calculateTotalAmount = 0 let calculateTotalDiscountAmount = 0 + let calcuateTotalWeight = 0 products.forEach((product) => { calculateTotalAmount += product.price.price * product.quantity calculateTotalDiscountAmount += (product.price.price - product.price.priceDiscount) * product.quantity + calcuateTotalWeight += product.weight * product.quantity + if (product.weight == 0) { + setCheckWeight(true) + } }) setTotalAmount(calculateTotalAmount) setTotalDiscountAmount(calculateTotalDiscountAmount) + setTotalWeight(calcuateTotalWeight * 1000) } }, [products]) + useEffect(() => { + const loadServiceRajaOngkir = async () => { + const body = { + origin: 155, + destination: selectedAddress.shipping.rajaongkirCityId, + weight: totalWeight, + courier: selectedCarrier, + originType: 'city', + destinationType: 'city' + } + setBiayaKirim(0) + const dataService = await axios('/api/rajaongkir-service?body=' + JSON.stringify(body)) + setListServiceExpedisi(dataService.data[0].costs) + if (dataService.data[0].costs[0]) { + setBiayaKirim(dataService.data[0].costs[0]?.cost[0].value) + setselectedExpedisiService( + dataService.data[0].costs[0]?.description + '-' + dataService.data[0].costs[0]?.service + ) + setEtd(dataService.data[0].costs[0]?.cost[0].etd) + toast.success('Silahkan Pilih Service Tipe') + } else { + toast.error('Tidak Ada Service, Silahkan Pilih Expedisi lain !') + } + } + if (selectedCarrier != 0 && selectedCarrier != 1 && totalWeight > 0) { + loadServiceRajaOngkir() + } else { + setListServiceExpedisi() + setBiayaKirim(0) + setselectedExpedisiService() + setEtd() + } + }, [selectedCarrier, selectedAddress, totalWeight]) + + useEffect(() => { + if (selectedServiceType) { + let serviceType = selectedServiceType.split(',') + setBiayaKirim(serviceType[0]) + setselectedExpedisiService(serviceType[1]) + setEtd(serviceType[2]) + } + }, [selectedServiceType]) + + useEffect(() => { + if (etd) { + let estimationDate = etd.split('-') + if (Array.isArray(estimationDate)) { + let from = new Date() + let to = new Date() + from.setDate(from.getDate() + parseInt(estimationDate[0])) + to.setDate(to.getDate() + parseInt(estimationDate[1])) + setEtdFix( + '(' + + from.getDate() + + ' ' + + from.toLocaleString('default', { month: 'short' }) + + ' - ' + + to.getDate() + + ' ' + + to.toLocaleString('default', { month: 'short' }) + + ')' + ) + } else { + let to = new Date() + to.setDate(to.getDate() + parseInt(10)) + setEtdFrom('>') + setEtdTo(to.getDate() + ' ' + to.toLocaleString('default', { month: 'short' })) + } + } + }, [etd]) + + useEffect(() => { + if (selectedExpedisi) { + let serviceType = selectedExpedisi.split(',') + setselectedCarrier(serviceType[0]) + setselectedCarrierId(serviceType[1]) + } + }, [selectedExpedisi]) + const poNumber = useRef(null) const poFile = useRef(null) @@ -127,6 +240,9 @@ const Checkout = () => { partner_shipping_id: auth.partnerId, partner_invoice_id: auth.partnerId, order_line: JSON.stringify(productOrder), + delivery_amount: biayaKirim, + carrier_id: selectedCarrierId, + delivery_service_type: selectedExpedisiService, type: 'sale_order' } if (poNumber.current.value) data.po_number = poNumber.current.value @@ -164,8 +280,37 @@ const Checkout = () => { <Divider /> - <PickupAddress label='Alamat Pickup' /> - + {/* <PickupAddress label='Alamat Pickup' /> */} + <SectionAddress + address={selectedAddress.shipping} + label='Alamat Kirim' + url='/my/address?select=shipping' + ></SectionAddress> + <Divider /> + <SectionAddress + address={selectedAddress.invoicing} + label='Alamat Penagihan' + url='/my/address?select=invoice' + ></SectionAddress> + <Divider /> + <SectionValidation + address={selectedAddress.invoicing} + checkWeigth={checkWeigth} + ></SectionValidation> + <Divider /> + <SectionExpedisi + address={selectedAddress.shipping} + listExpedisi={listExpedisi} + setSelectedExpedisi={setSelectedExpedisi} + checkWeigth={checkWeigth} + ></SectionExpedisi> + <Divider /> + <SectionListService + listserviceExpedisi={listserviceExpedisi} + setSelectedServiceType={setSelectedServiceType} + ></SectionListService> + <Divider /> + <Divider /> <Divider /> <div className='p-4 flex flex-col gap-y-4'> @@ -197,12 +342,23 @@ const Checkout = () => { <div className='text-gray_r-11'>PPN 11%</div> <div>{currencyFormat(taxTotal)}</div> </div> + <div className='flex gap-x-2 justify-between'> + <div className='text-gray_r-11'> + Biaya Kirim <p className='text-xs'>*Estimasi tiba {etdFix} </p> + </div> + <div>{currencyFormat(Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000)}</div> + </div> </div> <hr className='my-4 border-gray_r-6' /> <div className='flex gap-x-2 justify-between mb-4'> <div>Grand Total</div> <div className='font-semibold text-gray_r-12'> - {currencyFormat(totalAmount - totalDiscountAmount + taxTotal)} + {currencyFormat( + totalAmount - + totalDiscountAmount + + taxTotal + + Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000 + )} </div> </div> {/* <p className='text-caption-2 text-gray_r-10 mb-2'>*) Belum termasuk biaya pengiriman</p> */} @@ -244,7 +400,9 @@ const Checkout = () => { <button className='flex-1 btn-yellow' onClick={checkout} - disabled={isLoading || !products || products?.length == 0 || priceCheck} + disabled={ + isLoading || !products || products?.length == 0 || priceCheck || selectedExpedisi == 0 + } > {isLoading ? 'Loading...' : 'Lanjut Pembayaran'} </button> @@ -264,8 +422,35 @@ const Checkout = () => { <DesktopView> <div className='container mx-auto py-10 flex'> <div className='w-3/4 border border-gray_r-6 rounded bg-white'> - <PickupAddress label='Alamat Pickup' /> - + {/* <PickupAddress label='Alamat Pickup' /> */} + <SectionAddress + address={selectedAddress.shipping} + label='Alamat Kirim' + url='/my/address?select=shipping' + ></SectionAddress> + <Divider /> + <SectionAddress + address={selectedAddress.invoicing} + label='Alamat Penagihan' + url='/my/address?select=invoice' + ></SectionAddress> + <Divider /> + <SectionValidation + address={selectedAddress.invoicing} + checkWeigth={checkWeigth} + ></SectionValidation> + <Divider /> + <SectionExpedisi + address={selectedAddress.shipping} + listExpedisi={listExpedisi} + setSelectedExpedisi={setSelectedExpedisi} + checkWeigth={checkWeigth} + ></SectionExpedisi> + <Divider /> + <SectionListService + listserviceExpedisi={listserviceExpedisi} + setSelectedServiceType={setSelectedServiceType} + ></SectionListService> <Divider /> <div className='p-4'> @@ -300,6 +485,9 @@ const Checkout = () => { ? `| ${product?.attributes.join(', ')}` : ''} </div> + <div className='text-gray_r-11 mt-2'> + Berat item : {product?.weight} Kg + </div> </div> </td> <td> @@ -377,6 +565,13 @@ const Checkout = () => { <div className='text-gray_r-11'>PPN 11%</div> <div>{currencyFormat(taxTotal)}</div> </div> + <div className='flex gap-x-2 justify-between'> + <div className='text-gray_r-11'> + Biaya Kirim + <p className='text-xs'>*Estimasi tiba {etdFix} </p> + </div> + <div>{currencyFormat(Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000)}</div> + </div> </div> <hr className='my-4 border-gray_r-6' /> @@ -384,7 +579,12 @@ const Checkout = () => { <div className='flex gap-x-2 justify-between mb-4'> <div>Grand Total</div> <div className='font-semibold text-gray_r-12'> - {currencyFormat(totalAmount - totalDiscountAmount + taxTotal)} + {currencyFormat( + totalAmount - + totalDiscountAmount + + taxTotal + + Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000 + )} </div> </div> <p className='text-caption-2 text-gray_r-11 leading-5'> @@ -423,7 +623,14 @@ const Checkout = () => { <button className='w-full btn-yellow mt-4' onClick={checkout} - disabled={isLoading || !products || products?.length == 0 || priceCheck} + disabled={ + isLoading || + !products || + products?.length == 0 || + priceCheck || + selectedCarrier == 0 || + (selectedCarrier != 1 && biayaKirim == 0) + } > {isLoading ? 'Loading...' : 'Lanjut Pembayaran'} </button> @@ -468,6 +675,89 @@ const SectionAddress = ({ address, label, url }) => ( )} </div> ) + +const SectionValidation = ({ address, checkWeigth }) => + address?.rajaongkirCityId == 0 && ( + <BottomPopup active={true} title='Update Alamat'> + <div className='leading-7 text-gray_r-12/80'> + Silahkan Update Alamat Anda Melalui Tombol di bawah ini{' '} + </div> + <div className='flex justify-center mt-6 gap-x-4'> + <Link className='btn-solid-red w-full md:w-fit text-white' href={`/my/address/${address?.id}/edit`}> + Update Alamat + </Link> + </div> + </BottomPopup> + ) + +const SectionExpedisi = ({ address, listExpedisi, setSelectedExpedisi, checkWeigth }) => + address?.rajaongkirCityId > 0 && ( + <div className='p-4'> + <div className='flex justify-between items-center'> + <div className='font-medium'>Pilih Expedisi : </div> + <div> + <select className='form-input' onChange={(e) => setSelectedExpedisi(e.target.value)}> + <option value='0,0'>Pengiriman</option> + <option value='1,32'>SELF PICKUP</option> + {checkWeigth != true && + listExpedisi.map((expedisi) => ( + <option + disabled={checkWeigth} + value={expedisi.label + ',' + expedisi.carrierId} + key={expedisi.value} + > + {' '} + {expedisi.label.toUpperCase()}{' '} + </option> + ))} + </select> + </div> + </div> + {checkWeigth == true && ( + <p className='mt-2 text-gray_r-11'> + Opsi pengiriman hanya ada self pickup, ada berat item yang belum di setting, silahkan hub + admin di{' '} + <span> + <a className='text-danger-500' href='https://api.whatsapp.com/send?phone=628128080622'> + Link InI ! + </a> + </span> + </p> + )} + </div> + ) + +const SectionListService = ({ listserviceExpedisi, setSelectedServiceType }) => + listserviceExpedisi?.length > 0 && ( + <div className='p-4'> + <div className='flex justify-between items-center'> + <div className='font-medium'>Service Type Expedisi : </div> + <div> + <select className='form-input' onChange={(e) => setSelectedServiceType(e.target.value)}> + {listserviceExpedisi.map((service) => ( + <option + value={ + service.cost[0].value + + ',' + + service.description + + '-' + + service.service + + ',' + + service.cost[0].etd + } + key={service.service} + > + {' '} + {service.description} - {service.service.toUpperCase()} (Estimasi Tiba{' '} + {service.cost[0].etd} Hari) + </option> + ))} + </select> + </div> + </div> + </div> + ) + const PickupAddress = ({ label }) => ( <div className='p-4'> <div className='flex justify-between items-center'> diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx index 93234c53..0f9f02f6 100644 --- a/src/lib/variant/components/VariantCard.jsx +++ b/src/lib/variant/components/VariantCard.jsx @@ -39,6 +39,9 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => { {product.code || '-'} {product.attributes.length > 0 ? ` ・ ${product.attributes.join(', ')}` : ''} </p> + <p className='text-caption-2 text-gray_r-11 mt-1'> + Berat Item : {product?.weight} Kg + </p> <div className='flex flex-wrap gap-x-1 items-center mt-auto'> {product.price.discountPercentage > 0 && ( <> |
