From bb656eb35742fbb18fe9c700a3569c4765c65a1c Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 7 Aug 2025 15:33:20 +0700 Subject: (andri) tru --- src/lib/checkout/stores/stateQuotation.js | 30 +++++ src/lib/quotation/components/Quotation.jsx | 206 +++++++++++++++++------------ 2 files changed, 153 insertions(+), 83 deletions(-) create mode 100644 src/lib/checkout/stores/stateQuotation.js (limited to 'src') diff --git a/src/lib/checkout/stores/stateQuotation.js b/src/lib/checkout/stores/stateQuotation.js new file mode 100644 index 00000000..da84997a --- /dev/null +++ b/src/lib/checkout/stores/stateQuotation.js @@ -0,0 +1,30 @@ +import { create } from "zustand"; + +export const useQuotation = create((set) => ({ + products : null, + checkWeigth : false, + hasFlashSale : false, + checkoutValidation : false, + biayaKirim : 0, + etd : null, + unit : null, + selectedCourier : null, + selectedCourierId : null, + selectedService : null, + listExpedisi : [], + productSla : null, + setCheckWeight : (checkWeigth) => set({ checkWeigth }), + setHasFlashSale : (hasFlashSale) => set({ hasFlashSale }), + setCheckoutValidation : (checkoutValidation) => set({ checkoutValidation }), + setBiayaKirim : (biayaKirim) => set({ biayaKirim }), + setProducts : (products) => set({ products }), + setEtd : (etd) => set({ etd }), + setUnit : (unit) => set({ unit }), + setSelectedCourier : (selectedCourier) => set({ selectedCourier }), + setSelectedService : (selectedService) => set({ selectedService }), + setSelectedCourierId : (selectedCourierId) => set({ selectedCourierId }), + setExpedisi : (listExpedisi) => set({ listExpedisi }), + setProductSla : (productSla) => set({ productSla }) + + +})) \ No newline at end of file diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index 2f4d6c46..189c48ee 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -19,6 +19,8 @@ import Image from '@/core/components/elements/Image/Image'; import { useQuery } from 'react-query'; import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList'; import { Skeleton } from '@chakra-ui/react'; +import { useAddress } from '@/lib/checkout/stores/useAdress'; +import { useQuotation } from '@/lib/checkout/stores/stateQuotation'; import { PickupAddress, SectionAddress, @@ -31,11 +33,13 @@ import { import addressesApi from '@/lib/address/api/addressesApi'; import { getItemAddress } from '@/core/utils/address'; import ExpedisiList from '../../checkout/api/ExpedisiList'; -import axios from 'axios'; const { checkoutApi } = require('@/lib/checkout/api/checkoutApi'); const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi'); +import SectionExpedition from '@/lib/checkout/components/SectionExpedition'; + + const Quotation = () => { const PPN = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0; const router = useRouter(); @@ -51,16 +55,16 @@ const Quotation = () => { const { setRefreshCart } = useProductCartContext(); const SELF_PICKUP_ID = 32; - const [products, setProducts] = useState(null); + // const [products, setProducts] = useState(null); const [totalAmount, setTotalAmount] = useState(0); const [totalDiscountAmount, setTotalDiscountAmount] = useState(0); //start set up address and carrier const [selectedCarrierId, setselectedCarrierId] = useState(0); - const [listExpedisi, setExpedisi] = useState([]); + // const [listExpedisi, setExpedisi] = useState([]); const [selectedExpedisi, setSelectedExpedisi] = useState(0); - const [checkWeigth, setCheckWeight] = useState(false); - const [checkoutValidation, setCheckoutValidation] = useState(false); + // const [checkWeigth, setCheckWeight] = useState(false); + // const [checkoutValidation, setCheckoutValidation] = useState(false); const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false); const [listserviceExpedisi, setListServiceExpedisi] = useState([]); @@ -69,24 +73,54 @@ const Quotation = () => { const [selectedCarrier, setselectedCarrier] = useState(0); const [totalWeight, setTotalWeight] = useState(0); - const [biayaKirim, setBiayaKirim] = useState(0); + // const [biayaKirim, setBiayaKirim] = useState(0); const [selectedExpedisiService, setselectedExpedisiService] = useState(null); - const [etd, setEtd] = useState(null); + // const [etd, setEtd] = useState(null); const [etdFix, setEtdFix] = useState(null); const [isApproval, setIsApproval] = useState(false); const expedisiValidation = useRef(null); - const [selectedAddress, setSelectedAddress] = useState({ - shipping: null, - invoicing: null, - }); + // const [selectedAddress, setSelectedAddress] = useState({ + // shipping: null, + // invoicing: null, + // }); - const [addresses, setAddresses] = useState(null); + // const [addresses, setAddresses] = useState(null); const [note_websiteText, setselectedNote_websiteText] = useState(''); + const { + selectedAddress, + setSelectedAddress, + addresses, + setAddresses, + setAddressMaps, + setCoordinate, + setPostalCode, + } = useAddress(); + + const { + checkWeigth, + setCheckWeight, + hasFlashSale, + setHasFlashSale, + checkoutValidation, + setCheckoutValidation, + biayaKirim, + products, + setProducts, + etd, + unit, + selectedCourier, + selectedCourierId, + selectedService, + listExpedisi, + setExpedisi, + productSla + } = useQuotation(); + useEffect(() => { if (!auth) return; @@ -116,62 +150,88 @@ const Quotation = () => { return addresses[0]; }; + let ship = matchAddress('shipping'); + setSelectedAddress({ shipping: matchAddress('shipping'), invoicing: matchAddress('invoicing'), }); + setPostalCode(ship?.zip); + if (ship?.addressMap) { + setAddressMaps(ship?.addressMap); + setCoordinate({ + destination_latitude: ship?.latitude, + destination_longitude: ship?.longtitude, + }); + } }, [addresses]); - const loadExpedisi = async () => { - let dataExpedisi = await ExpedisiList(); - dataExpedisi = dataExpedisi.map((expedisi) => ({ - value: expedisi.id, - label: expedisi.name, - carrierId: expedisi.deliveryCarrierId, - })); - setExpedisi(dataExpedisi); - }; + useEffect(() => { + // voucher(); + const loadExpedisi = async () => { + let dataExpedisi = await ExpedisiList(); + dataExpedisi = dataExpedisi.map((expedisi) => ({ + value: expedisi.id, + label: expedisi.name, + carrierId: expedisi.deliveryCarrierId, + logo: expedisi.image, + })); + setExpedisi(dataExpedisi); + }; + + loadExpedisi(); - const loadServiceRajaOngkir = async () => { - setLoadingRajaOngkir(true); - const body = { - origin: 2127, - destination: selectedAddress.shipping.rajaongkirCityId, - weight: totalWeight, - courier: selectedCarrier, - originType: 'subdistrict', - destinationType: 'subdistrict', + const handlePopState = () => { + router.push('/shop/cart'); }; - setBiayaKirim(0); - const dataService = await axios( - '/api/rajaongkir-service?body=' + JSON.stringify(body) - ); - setLoadingRajaOngkir(false); - 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('Harap pilih tipe layanan pengiriman'); - } else { - toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'); - } - }; + + window.onpopstate = handlePopState; + + return () => { + window.onpopstate = null; + }; + }, []); + + // const loadServiceRajaOngkir = async () => { + // setLoadingRajaOngkir(true); + // const body = { + // origin: 2127, + // destination: selectedAddress.shipping.rajaongkirCityId, + // weight: totalWeight, + // courier: selectedCarrier, + // originType: 'subdistrict', + // destinationType: 'subdistrict', + // }; + // setBiayaKirim(0); + // const dataService = await axios( + // '/api/rajaongkir-service?body=' + JSON.stringify(body) + // ); + // setLoadingRajaOngkir(false); + // 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('Harap pilih tipe layanan pengiriman'); + // } else { + // toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'); + // } + // }; useEffect(() => { setCheckoutValidation(false); if (selectedCarrier != 0 && selectedCarrier != 1 && totalWeight > 0) { - loadServiceRajaOngkir(); + // loadServiceRajaOngkir(); } else { setListServiceExpedisi(); - setBiayaKirim(0); + // setBiayaKirim(0); setselectedExpedisiService(); - setEtd(); + // setEtd(); } }, [selectedCarrier, selectedAddress, totalWeight]); @@ -227,7 +287,7 @@ const Quotation = () => { }); } }; - loadExpedisi(); + // loadExpedisi(); // loadProducts() }, []); @@ -376,24 +436,11 @@ const Quotation = () => { {!isApproval && ( <> - + {/* */} )} - -
{products && ( @@ -401,7 +448,9 @@ const Quotation = () => {
- + {products && products.length > 0 && ( + + )}
Ringkasan Penawaran
@@ -522,23 +571,14 @@ const Quotation = () => { )} - {!isApproval && ( - - )} + {/* {!isApproval && ( + + )} */} - + {products && products.length > 0 && ( + + )} {/*
*/}
Detail Barang
Date: Mon, 11 Aug 2025 09:29:11 +0700 Subject: fix biteship quotation --- src/lib/checkout/components/SectionExpedition.jsx | 4 +- .../components/SectionQuotationExpedition.jsx | 369 +++++++++++++++++++++ src/lib/quotation/components/Quotation.jsx | 318 ++++++------------ 3 files changed, 469 insertions(+), 222 deletions(-) create mode 100644 src/lib/checkout/components/SectionQuotationExpedition.jsx (limited to 'src') diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx index 7a02c6e9..2e92ffbc 100644 --- a/src/lib/checkout/components/SectionExpedition.jsx +++ b/src/lib/checkout/components/SectionExpedition.jsx @@ -341,7 +341,7 @@ export default function SectionExpedition({ products }) {
-
+
{/* Custom Select Input Field */}
{checkoutValidation && ( - *silahkan pilih expedisi + *Silahkan pilih expedisi )}
diff --git a/src/lib/checkout/components/SectionQuotationExpedition.jsx b/src/lib/checkout/components/SectionQuotationExpedition.jsx new file mode 100644 index 00000000..b8ea04ef --- /dev/null +++ b/src/lib/checkout/components/SectionQuotationExpedition.jsx @@ -0,0 +1,369 @@ +'use client'; + +import { Skeleton } from '@chakra-ui/react'; +import axios from 'axios'; +import Image from 'next/image'; +import React, { useEffect, useState } from 'react'; +import { useQuery } from 'react-query'; +import toast from 'react-hot-toast'; +import { useAddress } from '../stores/useAdress'; +import { useQuotation } from '../stores/stateQuotation'; + +import currencyFormat from '@/core/utils/currencyFormat'; +import { formatShipmentRange } from '../utils/functionCheckouit'; +import odooApi from '@/core/api/odooApi'; + +function mappingItems(products) { + return products?.map((item) => ({ + name: item?.name, + description: `${item.code} - ${item.name}`, + value: item.price.priceDiscount, + weight: item.weight * 1000, + quantity: item.quantity, + })); +} + +function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) { + const courierMap = couriers.reduce((acc, item) => { + const { courier_name, courier_code, courier_service_code } = item; + const key = courier_code.toLowerCase(); + + if ( + !includeInstant && + (['hours'].includes(item.shipment_duration_unit.toLowerCase()) || + item.service_type === 'same_day') + ) { + return acc; + } + + if (!acc[key]) { + acc[key] = { + courier_name: item.courier_name, + courier_code: courier_code, + service_type: {}, + }; + } + + acc[key].service_type[courier_service_code] = { + service_name: item.courier_service_name, + duration: item.duration, + shipment_range: item.shipment_duration_range, + shipment_unit: item.shipment_duration_unit, + price: item.price, + service_type: courier_service_code, + description: item.description, + }; + + return acc; + }, {}); + + return couriersOdoo.map((courierOdoo) => { + const courierNameKey = courierOdoo.label.toLowerCase(); + const carrierId = courierOdoo.carrierId; + + const mappedCourier = courierMap[courierNameKey] || false; + + if (!mappedCourier) { + return { + ...courierOdoo, + courier: false, + }; + } + + return { + ...courierOdoo, + courier: { + ...mappedCourier, + courier_id_odoo: carrierId, + }, + }; + }); +} + +export default function SectionExpeditionQuotation({ products }) { + const { addressMaps, coordinate, postalCode } = useAddress(); + const [serviceOptions, setServiceOptions] = useState([]); + const [isOpen, setIsOpen] = useState(false); + const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false); + const [couriers, setCouriers] = useState(null); + const [slaProducts, setSlaProducts] = useState(null); + const [savedServiceOptions, setSavedServiceOptions] = useState([]); + + const { + checkWeigth, + checkoutValidation, + setBiayaKirim, + setUnit, + setEtd, + selectedCourier, + setSelectedCourier, + selectedService, + setSelectedService, + listExpedisi, + productSla, + setProductSla, + setSelectedCourierId, + } = useQuotation(); + + let destination = {}; + let items = mappingItems(products); + + if (addressMaps) { + destination = { + origin_latitude: -6.3031123, + origin_longitude: 106.7794934999, + ...coordinate, + }; + } else if (postalCode) { + destination = { + origin_postal_code: 14440, + destination_postal_code: postalCode, + }; + } + + const fetchSlaProducts = async () => { + try { + let productsMapped = products.map((item) => ({ + id: item.id, + quantity: item.quantity, + })); + + let data = { + products: JSON.stringify(productsMapped), + }; + const res = await odooApi('POST', `/api/v1/product/variants/sla`, data); + setSlaProducts(res); + } catch (error) { + console.error('Failed to fetch SLA:', error); + } + }; + + useEffect(() => { + fetchSlaProducts(); + }, []); + + useEffect(() => { + if (slaProducts) { + let productSla = slaProducts?.slaTotal; + if (slaProducts.slaUnit === 'jam') { + productSla = 1; + } + setProductSla(productSla); + } + }, [slaProducts]); + + const fetchExpedition = async () => { + const body = { + ...destination, + couriers: + 'gojek,grab,deliveree,lalamove,jne,tiki,ninja,lion,rara,sicepat,jnt,pos,idexpress,rpx,wahana,jdl,pos,anteraja,sap,paxel,borzo', + items, + }; + const response = await axios.get(`/api/biteship-service`, { + params: { body: JSON.stringify(body) }, + }); + return response; + }; + + const { data, isLoading } = useQuery( + ['expedition', JSON.stringify(destination), JSON.stringify(items)], + fetchExpedition, + { + enabled: + Boolean(Object.keys(destination).length) && + items?.length > 0 && + !checkWeigth && + onFocusSelectedCourier, + staleTime: Infinity, + cacheTime: Infinity, + } + ); + + useEffect(() => { + const instant = slaProducts?.includeInstant || false; + if (data) { + const couriers = reverseMappingCourier( + listExpedisi, + data?.data?.pricing, + instant + ); + setCouriers(couriers); + } + }, [data, slaProducts]); + + const onCourierChange = (courier) => { + setIsOpen(false); + setOnFocuseSelectedCourier(false); + setSelectedService(null); + setBiayaKirim(0); + if (courier !== 0 && courier !== 32) { + if (courier.courier) { + setSelectedCourier(courier.courier.courier_code); + setSelectedCourierId(courier.carrierId); + setServiceOptions(Object.values(courier.courier.service_type)); + } else { + if ( + (courier.label === 'GRAB' || courier.label === 'GOJEK') && + !addressMaps + ) { + toast.error( + `Maaf, layanan kurir ${courier.label} tidak tersedia karena belum mengatur PinPoint.` + ); + } else { + toast.error('Maaf, layanan tidak tersedia. Mohon pilih ekspedisi lain.'); + } + setServiceOptions([]); + } + } else { + setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null); + setSelectedCourierId(courier); + setServiceOptions([]); + } + }; + + const handleSelect = (service) => { + setSelectedService(service); + setBiayaKirim(service?.price); + setEtd(service?.shipment_range); + setUnit(service?.shipment_unit); + setIsOpen(false); + }; + + useEffect(() => { + if (serviceOptions.length > 0) { + setSavedServiceOptions(serviceOptions); + } + }, [serviceOptions]); + + return ( +
+
+
Pilih Ekspedisi:
+
+
setOnFocuseSelectedCourier(!onFocusSelectedCourier)} + > + {selectedCourier ? ( +
+ {selectedCourier} +
+ ) : ( + Pilih Expedisi + )} +
+ {onFocusSelectedCourier && ( +
+ {!isLoading ? ( + <> +
onCourierChange(32)} + className='p-2 hover:bg-gray-100 cursor-pointer' + > +

SELF PICKUP

+
+ {couriers?.map((courier) => ( +
onCourierChange(courier)} + className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer' + > +

{courier?.label}

+ {courier?.courier?.courier_name} +
+ ))} + + ) : ( + <> + + + + )} +
+ )} + {checkoutValidation && ( + + *Silahkan pilih ekspedisi + + )} +
+
+ + {checkWeigth && ( +

+ Mohon maaf, pengiriman hanya tersedia untuk self pickup karena ada barang + yang belum memiliki berat. Silakan hubungi admin via{' '} + + tautan ini + +

+ )} + + {(serviceOptions.length > 0 || selectedService) && + selectedCourier && + selectedCourier !== 32 && + selectedCourier !== 0 && ( +
+
Tipe Layanan Ekspedisi:
+
+
setIsOpen(!isOpen)} + > + {selectedService ? ( +
+ {selectedService.service_name} + + {currencyFormat( + Math.round((selectedService?.price * 1.1) / 1000) * 1000 + )} + +
+ ) : ( + Pilih layanan pengiriman + )} +
+ {isOpen && ( +
+ {serviceOptions.map((service) => ( +
handleSelect(service)} + className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer' + > +
+

{service.service_name}

+

+ {formatShipmentRange( + service.shipment_range, + service.shipment_unit, + productSla + )} +

+
+ + {currencyFormat( + Math.round((service?.price * 1.1) / 1000) * 1000 + )} + +
+ ))} +
+ )} +
+
+ )} +
+ ); +} diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index 189c48ee..f0791512 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -10,7 +10,6 @@ import { deleteItemCart, getCart, getItemCart } from '@/core/utils/cart'; import currencyFormat from '@/core/utils/currencyFormat'; import { toast } from 'react-hot-toast'; import { useProductCartContext } from '@/contexts/ProductCartContext'; -// import checkoutApi from '@/lib/checkout/api/checkoutApi' import { useRouter } from 'next/router'; import VariantGroupCard from '@/lib/variant/components/VariantGroupCard'; import MobileView from '@/core/components/views/MobileView'; @@ -20,12 +19,10 @@ import { useQuery } from 'react-query'; import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList'; import { Skeleton } from '@chakra-ui/react'; import { useAddress } from '@/lib/checkout/stores/useAdress'; -import { useQuotation } from '@/lib/checkout/stores/stateQuotation'; +import { useCheckout } from '@/lib/checkout/stores/stateCheckout'; import { PickupAddress, SectionAddress, - SectionExpedisi, - SectionListService, SectionValidation, calculateEstimatedArrival, splitDuration, @@ -33,13 +30,12 @@ import { import addressesApi from '@/lib/address/api/addressesApi'; import { getItemAddress } from '@/core/utils/address'; import ExpedisiList from '../../checkout/api/ExpedisiList'; +import SectionQuotationExpedition from '@/lib/checkout/components/SectionQuotationExpedition'; +import { useQuotation } from '@/lib/checkout/stores/stateQuotation'; const { checkoutApi } = require('@/lib/checkout/api/checkoutApi'); const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi'); -import SectionExpedition from '@/lib/checkout/components/SectionExpedition'; - - const Quotation = () => { const PPN = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0; const router = useRouter(); @@ -55,41 +51,12 @@ const Quotation = () => { const { setRefreshCart } = useProductCartContext(); const SELF_PICKUP_ID = 32; - // const [products, setProducts] = useState(null); - const [totalAmount, setTotalAmount] = useState(0); + const [totalAmount, setTotalAmount] = useState(0); const [totalDiscountAmount, setTotalDiscountAmount] = useState(0); - - //start set up address and carrier - const [selectedCarrierId, setselectedCarrierId] = useState(0); - // const [listExpedisi, setExpedisi] = useState([]); - const [selectedExpedisi, setSelectedExpedisi] = useState(0); - // const [checkWeigth, setCheckWeight] = useState(false); - // const [checkoutValidation, setCheckoutValidation] = useState(false); - const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false); - - const [listserviceExpedisi, setListServiceExpedisi] = useState([]); - const [selectedServiceType, setSelectedServiceType] = useState(null); - - const [selectedCarrier, setselectedCarrier] = useState(0); - const [totalWeight, setTotalWeight] = useState(0); - - // const [biayaKirim, setBiayaKirim] = useState(0); - const [selectedExpedisiService, setselectedExpedisiService] = useState(null); - // const [etd, setEtd] = useState(null); - const [etdFix, setEtdFix] = useState(null); - const [isApproval, setIsApproval] = useState(false); - - const expedisiValidation = useRef(null); - - // const [selectedAddress, setSelectedAddress] = useState({ - // shipping: null, - // invoicing: null, - // }); - - // const [addresses, setAddresses] = useState(null); - const [note_websiteText, setselectedNote_websiteText] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [etdFix, setEtdFix] = useState(null); const { selectedAddress, @@ -102,15 +69,13 @@ const Quotation = () => { } = useAddress(); const { + products, + setProducts, checkWeigth, setCheckWeight, - hasFlashSale, - setHasFlashSale, checkoutValidation, setCheckoutValidation, biayaKirim, - products, - setProducts, etd, unit, selectedCourier, @@ -118,8 +83,16 @@ const Quotation = () => { selectedService, listExpedisi, setExpedisi, - productSla + productSla, + setProductSla, + setBiayaKirim, + setUnit, + setEtd, + setSelectedCourier, + setSelectedService, + setSelectedCourierId } = useQuotation(); + useEffect(() => { if (!auth) return; @@ -167,7 +140,6 @@ const Quotation = () => { }, [addresses]); useEffect(() => { - // voucher(); const loadExpedisi = async () => { let dataExpedisi = await ExpedisiList(); dataExpedisi = dataExpedisi.map((expedisi) => ({ @@ -192,182 +164,104 @@ const Quotation = () => { }; }, []); - // const loadServiceRajaOngkir = async () => { - // setLoadingRajaOngkir(true); - // const body = { - // origin: 2127, - // destination: selectedAddress.shipping.rajaongkirCityId, - // weight: totalWeight, - // courier: selectedCarrier, - // originType: 'subdistrict', - // destinationType: 'subdistrict', - // }; - // setBiayaKirim(0); - // const dataService = await axios( - // '/api/rajaongkir-service?body=' + JSON.stringify(body) - // ); - // setLoadingRajaOngkir(false); - // 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('Harap pilih tipe layanan pengiriman'); - // } else { - // toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'); - // } - // }; - - useEffect(() => { - setCheckoutValidation(false); - - if (selectedCarrier != 0 && selectedCarrier != 1 && totalWeight > 0) { - // loadServiceRajaOngkir(); - } else { - setListServiceExpedisi(); - // setBiayaKirim(0); - setselectedExpedisiService(); - // setEtd(); - } - }, [selectedCarrier, selectedAddress, totalWeight]); - - useEffect(() => { - if (selectedExpedisi) { - let serviceType = selectedExpedisi.split(','); - if (serviceType[0] === 0) return; - - setselectedCarrier(serviceType[0]); - setselectedCarrierId(serviceType[1]); - setListServiceExpedisi([]); - } - }, [selectedExpedisi]); - - useEffect(() => { - if (selectedServiceType) { - let serviceType = selectedServiceType.split(','); - setBiayaKirim(serviceType[0]); - setselectedExpedisiService(serviceType[1]); - setEtd(serviceType[2]); - } - }, [selectedServiceType]); - - useEffect(() => { - if (etd) setEtdFix(calculateEstimatedArrival(etd)); - }, [etd]); - useEffect(() => { if (isApproval) { - setselectedCarrierId(1); - setselectedExpedisiService('indoteknik'); + setSelectedCourierId(1); + setSelectedCourier('indoteknik'); } }, [isApproval]); - // end set up address and carrier - useEffect(() => { - const loadProducts = async () => { - const cart = getCart(); - const variantIds = _.filter(cart, (o) => o.selected == true) - .map((o) => o.productId) - .join(','); - const dataProducts = await CartApi({ variantIds }); - const productsWithQuantity = dataProducts?.map((product) => { - return { - ...product, - quantity: getItemCart({ productId: product.id }).quantity, - }; - }); - if (productsWithQuantity) { - Promise.all(productsWithQuantity).then((resolvedProducts) => { - setProducts(resolvedProducts); - }); - } - }; - // loadExpedisi(); - // loadProducts() - }, []); - - useEffect(() => { - setProducts(cartCheckout?.products); - setCheckWeight(cartCheckout?.hasProductWithoutWeight); - setTotalWeight(cartCheckout?.totalWeight.g); + if (cartCheckout) { + setProducts(cartCheckout?.products); + setCheckWeight(cartCheckout?.hasProductWithoutWeight); + } }, [cartCheckout]); useEffect(() => { if (products) { - let calculateTotalAmount = 0; - let calculateTotalDiscountAmount = 0; - products.forEach((product) => { - calculateTotalAmount += product.price.price * product.quantity; - calculateTotalDiscountAmount += - (product.price.price - product.price.priceDiscount) * - product.quantity; - }); - setTotalAmount(calculateTotalAmount); - setTotalDiscountAmount(calculateTotalDiscountAmount); + const calculateTotals = () => { + let calculateTotalAmount = 0; + let calculateTotalDiscountAmount = 0; + + products.forEach((product) => { + calculateTotalAmount += product.price.price * product.quantity; + calculateTotalDiscountAmount += + (product.price.price - product.price.priceDiscount) * product.quantity; + }); + + setTotalAmount(calculateTotalAmount); + setTotalDiscountAmount(calculateTotalDiscountAmount); + }; + + calculateTotals(); } }, [products]); - const [isLoading, setIsLoading] = useState(false); + useEffect(() => { + if (etd) { + setEtdFix(calculateEstimatedArrival(etd)); + } + }, [etd]); const checkout = async () => { - // validation checkout - if (selectedExpedisi === 0 && !isApproval) { + // Validation + if (!selectedCourierId && !isApproval) { setCheckoutValidation(true); - if (expedisiValidation.current) { - const position = expedisiValidation.current.getBoundingClientRect(); - window.scrollTo({ - top: position.top - 300 + window.pageYOffset, - behavior: 'smooth', - }); - } + toast.error('Silahkan pilih ekspedisi'); return; } - if (selectedCarrier != 1 && biayaKirim == 0 && !isApproval) { + + if (selectedCourierId !== SELF_PICKUP_ID && biayaKirim === 0 && !isApproval) { toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'); return; } - if (!products || products.length == 0) return; + if (!products || products.length === 0) return; - if (isApproval && note_websiteText == '') { + if (isApproval && note_websiteText === '') { toast.error('Maaf, Note wajib dimasukkan.'); return; } setIsLoading(true); - const productOrder = products.map((product) => ({ - product_id: product.id, - quantity: product.quantity, - })); - let data = { - partner_shipping_id: selectedAddress.shipping.id, - partner_invoice_id: selectedAddress.invoicing.id, - user_id: auth.id, - order_line: JSON.stringify(productOrder), - delivery_amount: biayaKirim, - carrier_id: selectedCarrierId, - estimated_arrival_days: splitDuration(etd), - delivery_service_type: selectedExpedisiService, - note_website: note_websiteText, - }; + try { + const productOrder = products.map((product) => ({ + product_id: product.id, + quantity: product.quantity, + })); - const isSuccess = await checkoutApi({ data }); - setIsLoading(false); - if (isSuccess?.id) { - for (const product of products) deleteItemCart({ productId: product.id }); - router.push(`/shop/quotation/finish?id=${isSuccess.id}`); - setRefreshCart(true); - return; + const data = { + partner_shipping_id: selectedAddress.shipping.id, + partner_invoice_id: selectedAddress.invoicing.id, + user_id: auth.id, + order_line: JSON.stringify(productOrder), + delivery_amount: biayaKirim, + carrier_id: selectedCourierId, + estimated_arrival_days: splitDuration(etd), + delivery_service_type: selectedService?.service_type || selectedCourier, + note_website: note_websiteText, + }; + + const isSuccess = await checkoutApi({ data }); + + if (isSuccess?.id) { + for (const product of products) { + deleteItemCart({ productId: product.id }); + } + router.push(`/shop/quotation/finish?id=${isSuccess.id}`); + setRefreshCart(true); + } else { + toast.error('Gagal melakukan transaksi, terjadi kesalahan internal'); + } + } catch (error) { + toast.error('Terjadi kesalahan saat memproses quotation'); + } finally { + setIsLoading(false); } - - toast.error('Gagal melakukan transaksi, terjadi kesalahan internal'); }; + const taxTotal = (totalAmount - totalDiscountAmount) * (PPN - 1); return ( @@ -387,21 +281,21 @@ const Quotation = () => { - {selectedCarrierId == SELF_PICKUP_ID && ( + {selectedCourierId == SELF_PICKUP_ID && (