diff options
| author | trisusilo48 <tri.susilo@altama.co.id> | 2024-11-26 09:46:07 +0700 |
|---|---|---|
| committer | trisusilo48 <tri.susilo@altama.co.id> | 2024-11-26 09:46:07 +0700 |
| commit | 821d218ff687a585c99937948989408541b596e4 (patch) | |
| tree | 6254c5088a05a091427dca495b7a8b93601164a0 | |
| parent | f7dad0695d83a4e59b9423d6e7aedb554f716b52 (diff) | |
filter biteship courier sesuikan dengan courier dari odoo
| -rw-r--r-- | src/lib/checkout/components/Checkout.jsx | 185 | ||||
| -rw-r--r-- | src/lib/checkout/components/SectionExpedition.jsx | 118 | ||||
| -rw-r--r-- | src/lib/checkout/stores/stateCheckout.js | 12 | ||||
| -rw-r--r-- | src/lib/checkout/utils/functionCheckouit.js | 79 |
4 files changed, 250 insertions, 144 deletions
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 92a94834..38e11038 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -35,6 +35,7 @@ import { getVoucher } from '../api/getVoucher'; import { useAddress } from '../stores/useAdress'; import SectionExpedition from './SectionExpedition'; import { useCheckout } from '../stores/stateCheckout'; +import { formatShipmentRange, getToDate } from '../utils/functionCheckouit'; const SELF_PICKUP_ID = 32; @@ -128,15 +129,14 @@ const Checkout = () => { 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 [selectedServiceType, setSelectedServiceType] = useState(null); const [selectedExpedisiService, setselectedExpedisiService] = useState(null); - const [etd, setEtd] = useState(null); - const [etdFix, setEtdFix] = useState(null); + // const [etd, setEtd] = useState(null); + // const [etdFix, setEtdFix] = useState(null); const [bottomPopup, SetBottomPopup] = useState(null); const [bottomPopupTnC, SetBottomPopupTnC] = useState(null); const [itemTnC, setItemTnC] = useState(null); @@ -151,7 +151,7 @@ const Checkout = () => { const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false); const [grandTotal, setGrandTotal] = useState(0); - const {checkWeigth, setCheckWeight, hasFlashSale, setHasFlashSale, checkoutValidation, setCheckoutValidation, biayaKirim, setBiayaKirim, products, setProducts} = useCheckout(); + const {checkWeigth, setCheckWeight, hasFlashSale, setHasFlashSale, checkoutValidation, setCheckoutValidation, biayaKirim, products, setProducts, etd, unit, selectedCourier, selectedService, listExpedisi, setExpedisi} = useCheckout(); const expedisiValidation = useRef(null); @@ -290,6 +290,7 @@ const Checkout = () => { window.onpopstate = handlePopState; + return () => { window.onpopstate = null; }; @@ -312,70 +313,70 @@ const Checkout = () => { setHasFlashSale(hasFlashSale); }, [cartCheckout]); - useEffect(() => { - setCheckoutValidation(false); - 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.'); - } - }; - 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) setEtdFix(calculateEstimatedArrival(etd)); - }, [etd]); - - useEffect(() => { - if (selectedExpedisi) { - let serviceType = selectedExpedisi.split(','); - if (serviceType[0] === 0) return; - - setselectedCarrier(serviceType[0]); - setselectedCarrierId(serviceType[1]); - setListServiceExpedisi([]); - } - }, [selectedExpedisi]); + // useEffect(() => { + // setCheckoutValidation(false); + // 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.'); + // } + // }; + // 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) setEtdFix(calculateEstimatedArrival(etd)); + // }, [etd]); + + // useEffect(() => { + // if (selectedExpedisi) { + // let serviceType = selectedExpedisi.split(','); + // if (serviceType[0] === 0) return; + + // setselectedCarrier(serviceType[0]); + // setselectedCarrierId(serviceType[1]); + // setListServiceExpedisi([]); + // } + // }, [selectedExpedisi]); const poNumber = useRef(null); const poFile = useRef(null); @@ -403,7 +404,7 @@ const Checkout = () => { }); return; } - if (selectedExpedisi === 0) { + if (selectedCourier === 0 || !selectedCourier) { setCheckoutValidation(true); if (expedisiValidation.current) { const position = expedisiValidation.current.getBoundingClientRect(); @@ -414,7 +415,11 @@ const Checkout = () => { } return; } - if (selectedCarrier != 1 && biayaKirim == 0) { + if(!selectedService){ + toast.error('Harap pilih tipe layanan pengiriman'); + return; + } + if (selectedCourier != 1 && biayaKirim == 0) { toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'); return; } @@ -432,15 +437,14 @@ const Checkout = () => { user_id: auth.id, order_line: JSON.stringify(productOrder), delivery_amount: biayaKirim, - carrier_id: selectedCarrierId, - estimated_arrival_days: splitDuration(etd), - delivery_service_type: selectedExpedisiService, + carrier_id: selectedCourier, + estimated_arrival_days: getToDate(etd, unit), + delivery_service_type: selectedService?.service_type, flash_sale: hasFlashSale, // dibuat negasi untuk ngetest kebalikan nilai false voucher: activeVoucher, voucher_shipping: activeVoucherShipping, type: 'sale_order', }; - if (query) { data.source = 'buy'; } @@ -487,24 +491,6 @@ const Checkout = () => { )}`; } } - - /* const midtrans = async () => { - for (const product of products) deleteItemCart({ productId: product.id }); - if (grandTotal > 0) { - const payment = await axios.post( - `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${isCheckouted.id}` - ); - setIsLoading(false); - window.location.href = payment.data.redirectUrl; - } else { - window.location.href = `${ - process.env.NEXT_PUBLIC_SELF_HOST - }/shop/checkout/success?order_id=${isCheckouted.name.replace( - /\//g, - '-' - )}`; - } - };*/ }; const handlingActivateCode = async () => { @@ -569,9 +555,6 @@ const Checkout = () => { cartCheckout?.discountVoucher + (cartCheckout?.discountVoucherShipping || 0); - - console.log('etd', etd, calculateEstimatedArrival(etd), splitDuration(etd)); - return ( <> <BottomPopup @@ -1068,7 +1051,7 @@ const Checkout = () => { )} <Divider /> <SectionValidation address={selectedAddress.invoicing} /> - <SectionExpedisi + {/* <SectionExpedisi address={selectedAddress.shipping} listExpedisi={listExpedisi} setSelectedExpedisi={setSelectedExpedisi} @@ -1081,7 +1064,7 @@ const Checkout = () => { <SectionListService listserviceExpedisi={listserviceExpedisi} setSelectedServiceType={setSelectedServiceType} - /> + /> */} <div className='p-4 flex flex-col gap-y-4'> {!!products && @@ -1168,7 +1151,7 @@ const Checkout = () => { </div> <div className='flex gap-x-2 justify-between'> <div className='text-gray_r-11'> - Biaya Kirim <p className='text-xs mt-1'>{etdFix}</p> + Biaya Kirim <p className='text-xs mt-1'>{formatShipmentRange(etd, unit)}</p> </div> <div> {currencyFormat( @@ -1367,7 +1350,7 @@ const Checkout = () => { {products && <SectionExpedition products={products} />} <Divider /> <SectionValidation address={selectedAddress.invoicing} /> - <SectionExpedisi + {/* <SectionExpedisi address={selectedAddress.shipping} listExpedisi={listExpedisi} setSelectedExpedisi={setSelectedExpedisi} @@ -1380,7 +1363,7 @@ const Checkout = () => { <SectionListService listserviceExpedisi={listserviceExpedisi} setSelectedServiceType={setSelectedServiceType} - /> + /> */} <div className='p-4'> <div className='font-medium mb-6'>Detail Pesanan</div> @@ -1474,7 +1457,7 @@ const Checkout = () => { <div className='flex gap-x-2 justify-between'> <div className='text-gray_r-11'> Biaya Kirim - <p className='text-xs mt-1'>{etdFix}</p> + <p className='text-xs mt-1'>{formatShipmentRange(etd, unit)}</p> </div> <div> {currencyFormat( diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx index 27224e5b..be40a577 100644 --- a/src/lib/checkout/components/SectionExpedition.jsx +++ b/src/lib/checkout/components/SectionExpedition.jsx @@ -1,4 +1,4 @@ -import { Spinner } from '@chakra-ui/react'; +import { Skeleton, Spinner } from '@chakra-ui/react'; import axios from 'axios'; import { AnimatePresence, motion } from 'framer-motion'; import React, { useState } from 'react'; @@ -14,15 +14,25 @@ function mappingItems(products) { name: item.parent.name, description: `${item.code} - ${item.name}`, value: item.price.priceDiscount, - weight: item.weight * 1000 * item.quantity, + weight: item.weight * 1000, quantity: item.quantity, canInstant: item.availableQuantity > item.quantity ? true : false, })); } -function mappingCourier(couriers, notIncludeInstant = false) { +function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) { + const validCourierMap = couriersOdoo.reduce((acc, courier) => { + acc[courier.label.toLowerCase()] = courier.carrierId; + return acc; + }, {}); + return couriers?.reduce((result, item) => { - const { courier_code, courier_service_code } = item; + const { courier_name, courier_code, courier_service_code } = item; + if (!validCourierMap[courier_name.toLowerCase()]) { + return result; // Jika tidak ada, lewati item ini + } + + if ( notIncludeInstant && ['hours'].includes(item.shipment_duration_unit.toLowerCase()) @@ -30,16 +40,20 @@ function mappingCourier(couriers, notIncludeInstant = false) { return result; } + const carrierId = validCourierMap[courier_name]; + // Jika courier_code belum ada di result, buat objek baru untuknya if (!result[courier_code]) { result[courier_code] = { courier_name: item.courier_name, courier_code: courier_code, + courier_id_odoo : carrierId, service_type: { [courier_service_code]: { service_name: item.courier_service_name, duration: item.duration, - shipment_duration: item.duration, + shipment_range: item.shipment_duration_range, + shipment_unit: item.shipment_duration_unit, price: item.price, service_type: item.service_type, description: item.description, @@ -50,6 +64,8 @@ function mappingCourier(couriers, notIncludeInstant = false) { result[courier_code].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, shipment_duration: item.duration, price: item.price, service_type: item.service_type, @@ -92,18 +108,27 @@ function hasCanInstantFalse(items) { export default function SectionExpedition({ products }) { const { addressMaps, coordinate, postalCode } = useAddress(); const { control, handleSubmit } = useForm(); - const [selectedCourier, setSelectedCourier] = useState(''); const [serviceOptions, setServiceOptions] = useState([]); - const [selectedService, setSelectedService] = useState(null); const [isOpen, setIsOpen] = useState(false); + const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false); - const { checkWeigth, checkoutValidation } = useCheckout(); + const { + checkWeigth, + checkoutValidation, + setBiayaKirim, + setUnit, + setEtd, + selectedCourier, + setSelectedCourier, + selectedService, + setSelectedService, + listExpedisi, + } = useCheckout(); let destination = {}; let items = mappingItems(products); let notIncludeInstant = hasCanInstantFalse(items); - console.log('instanCourier', items); if (addressMaps) { destination = { origin_latitude: -6.3031123, @@ -112,7 +137,7 @@ export default function SectionExpedition({ products }) { }; } else if (postalCode) { destination = { - origin_postal_code: 12440, + origin_postal_code: 14440, destination_postal_code: postalCode, }; } @@ -141,23 +166,26 @@ export default function SectionExpedition({ products }) { enabled: Boolean(Object.keys(destination).length) && items?.length > 0 && - !checkWeigth, + !checkWeigth && + onFocusSelectedCourier, staleTime: Infinity, cacheTime: Infinity, } ); - console.log('data', data); + const couriers = + mappingCourier(listExpedisi, data?.data?.pricing, notIncludeInstant) || + null; - const couriers = mappingCourier(data?.data?.pricing, true) || null; + console.log('ini scourier', data?.data?.pricing) const onCourierChange = (e) => { setIsOpen(false); const courier = e.target.value; setSelectedService(null); setSelectedCourier(courier); - console.log('courier', courier); - // Menentukan layanan berdasarkan pengiriman yang dipilih + // setSelectedCourierId(Object.values(couriers[courier]?.courier_id_odoo); + setBiayaKirim(0); if (courier && courier !== '0' && courier !== '32' && couriers[courier]) { setServiceOptions(Object.values(couriers[courier]?.service_type)); } else { @@ -165,12 +193,15 @@ export default function SectionExpedition({ products }) { } }; - const onSubmit = (data) => { + const onSubmit = (data) => {1 console.log(data); }; const handleSelect = (service) => { setSelectedService(service); + setBiayaKirim(service?.price); + setEtd(service?.shipment_range); + setUnit(service?.shipment_unit); setIsOpen(false); }; @@ -184,37 +215,38 @@ export default function SectionExpedition({ products }) { <select className={`form-input `} onChange={onCourierChange} + onMouseDown={() => setOnFocuseSelectedCourier(true)} required > - <option value='0'>Pilih Pengiriman</option> - <option value='32'>SELF PICKUP</option> - {couriers && - Object.values(couriers)?.map((expedisi) => ( - <option - value={expedisi.courier_code} - key={expedisi.courier_name} - > - {' '} - {expedisi.courier_name} + {!isLoading ? ( + <> + <option value='0'>Pilih Pengiriman</option> + <option value='32'>SELF PICKUP</option> + {couriers && + Object.values(couriers)?.map((expedisi) => ( + <option + value={expedisi.courier_code} + key={expedisi.courier_name} + > + {' '} + {expedisi.courier_name} + </option> + ))} + </> + ) : ( + <> + <option disabled className='skeleton-option'> + <Skeleton height={40} containerClassName='w-full' /> </option> - ))} - </select> - - <AnimatePresence> - {isLoading && ( - <motion.div - initial={{ opacity: 0, width: 0 }} - animate={{ opacity: 1, width: '28px' }} - exit={{ opacity: 0, width: 0 }} - transition={{ - duration: 0.25, - }} - className='overflow-hidden' - > - <Spinner thickness='3px' speed='0.5s' color='red.500' /> - </motion.div> + <option disabled className='skeleton-option'> + <Skeleton height={40} containerClassName='w-full' /> + </option> + <option disabled className='skeleton-option'> + <Skeleton height={40} containerClassName='w-full' /> + </option> + </> )} - </AnimatePresence> + </select> </div> {checkoutValidation && ( <span className='text-sm text-red-500'> diff --git a/src/lib/checkout/stores/stateCheckout.js b/src/lib/checkout/stores/stateCheckout.js index 97b0c64e..4fefbbed 100644 --- a/src/lib/checkout/stores/stateCheckout.js +++ b/src/lib/checkout/stores/stateCheckout.js @@ -7,10 +7,22 @@ export const useCheckout = create((set) => ({ checkoutValidation : false, biayaKirim : 0, etd : null, + unit : null, + selectedCourier : null, + selectedCourierId : null, + selectedService : null, + listExpedisi : [], 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 }) + }))
\ No newline at end of file diff --git a/src/lib/checkout/utils/functionCheckouit.js b/src/lib/checkout/utils/functionCheckouit.js new file mode 100644 index 00000000..b299f289 --- /dev/null +++ b/src/lib/checkout/utils/functionCheckouit.js @@ -0,0 +1,79 @@ +export function formatShipmentRange( + shipmentDurationRange, + shipmentDurationUnit +) { + if (!shipmentDurationRange || !shipmentDurationUnit) { + return ''; + } + let minRange, maxRange; + + // Cek apakah durasi berupa range atau angka tunggal + if (shipmentDurationRange.includes('-')) { + [minRange, maxRange] = shipmentDurationRange.split(' - ').map(Number); + } else { + minRange = maxRange = Number(shipmentDurationRange); // Jika angka tunggal + } + + const start = new Date(); // Tanggal saat ini + + let minDate, maxDate; + + // Hitung estimasi berdasarkan unit waktu + if (shipmentDurationUnit === 'days' || shipmentDurationUnit === 'day') { + minDate = new Date(start); + minDate.setDate(start.getDate() + (minRange + 3)); + + maxDate = new Date(start); + maxDate.setDate(start.getDate() + (maxRange + 3)); + } else if (shipmentDurationUnit === 'hours') { + minDate = new Date(start.getTime() + (minRange + 3) * 60 * 60 * 1000); + maxDate = new Date(start.getTime() + (maxRange + 3) * 60 * 60 * 1000); + } else { + throw new Error("Unsupported unit. Please use 'days' or 'hours'."); + } + + console.log('min max', minDate, maxDate); + + const minDateStr = formatDate(minDate); + const maxDateStr = formatDate(maxDate); + if (minDateStr === maxDateStr) { + return `Estimasi tiba ${minDateStr}`; + } + return `Estimasi tiba ${minDateStr} - ${maxDateStr}`; +} + +export function getToDate(shipmentDurationRange, shipmentDurationUnit) { + if (!shipmentDurationRange || !shipmentDurationUnit) { + return ''; + } + const start = new Date(); // Tanggal saat ini + + let maxRange; + + // Cek apakah durasi berupa range atau angka tunggal + if (shipmentDurationRange.includes('-')) { + [, maxRange] = shipmentDurationRange.split(' - ').map(Number); + } else { + maxRange = Number(shipmentDurationRange); // Jika angka tunggal + } + + let maxDate; + + // Hitung estimasi berdasarkan unit waktu + if (shipmentDurationUnit === 'days' || shipmentDurationUnit === 'day') { + maxDate = new Date(start); + maxDate.setDate(start.getDate() + (maxRange + 3)); + } else if (shipmentDurationUnit === 'hours') { + maxDate = new Date(start.getTime() + (maxRange + 3) * 60 * 60 * 1000); + } else { + throw new Error("Unsupported unit. Please use 'days' or 'hours'."); + } + + return formatDate(maxDate); +} + +function formatDate(date) { + const day = date.getDate(); + const month = date.toLocaleString('default', { month: 'short' }); + return `${day} ${month}`; +} |
