summaryrefslogtreecommitdiff
path: root/src/lib/checkout/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/checkout/components')
-rw-r--r--src/lib/checkout/components/Checkout.jsx310
-rw-r--r--src/lib/checkout/components/SectionExpedition.jsx503
2 files changed, 707 insertions, 106 deletions
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 5256a328..0b386c30 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -28,10 +28,15 @@ import getFileBase64 from '@/core/utils/getFileBase64';
import { gtagPurchase } from '@/core/utils/googleTag';
import whatsappUrl from '@/core/utils/whatsappUrl';
import addressesApi from '@/lib/address/api/addressesApi';
+import { MapPinIcon } from 'lucide-react';
import CartItem from '~/modules/cart/components/Item.tsx';
import ExpedisiList from '../api/ExpedisiList';
import { findVoucher, getVoucher, getVoucherNew } 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;
const { checkoutApi } = require('../api/checkoutApi');
@@ -68,14 +73,28 @@ const Checkout = () => {
source: query,
voucher: activeVoucher,
voucher_shipping: activeVoucherShipping,
- })
+ }),
+ //biteship
+ {
+ keepPreviousData: true, // Menjaga data sebelumnya sampai data baru tersedia
+ }
);
- const [selectedAddress, setSelectedAddress] = useState({
- shipping: null,
- invoicing: null,
- });
- const [addresses, setAddresses] = useState(null);
+ // const [selectedAddress, setSelectedAddress] = useState({
+ // shipping: null,
+ // invoicing: null,
+ // });
+ // const [addresses, setAddresses] = useState(null);
+
+ const {
+ selectedAddress,
+ setSelectedAddress,
+ addresses,
+ setAddresses,
+ setAddressMaps,
+ setCoordinate,
+ setPostalCode,
+ } = useAddress();
useEffect(() => {
if (!auth) return;
@@ -105,26 +124,37 @@ const Checkout = () => {
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 [products, setProducts] = useState(null);
+ // const [products, setProducts] = useState(null);
const [totalWeight, setTotalWeight] = useState(0);
const [priceCheck, setPriceCheck] = useState(false);
- const [listExpedisi, setExpedisi] = useState([]);
+ // 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);
+ //new release
+ // 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);
+ // 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);
@@ -135,12 +165,31 @@ const Checkout = () => {
const [findCodeVoucher, SetFindVoucher] = useState(null);
const [selisihHargaCode, SetSelisihHargaCode] = useState(null);
const [buttonTerapkan, SetButtonTerapkan] = useState(false);
- const [checkoutValidation, setCheckoutValidation] = useState(false);
+ // const [checkoutValidation, setCheckoutValidation] = useState(false);
const [loadingVoucher, setLoadingVoucher] = useState(true);
const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false);
const [grandTotal, setGrandTotal] = useState(0);
const [hasFlashSale, setHasFlashSale] = useState(false);
+ const {
+ checkWeigth,
+ setCheckWeight,
+ hasFlashSale,
+ setHasFlashSale,
+ checkoutValidation,
+ setCheckoutValidation,
+ biayaKirim,
+ products,
+ setProducts,
+ etd,
+ unit,
+ selectedCourier,
+ selectedCourierId,
+ selectedService,
+ listExpedisi,
+ setExpedisi,
+ productSla
+ } = useCheckout();
const expedisiValidation = useRef(null);
const voucher = async () => {
@@ -296,6 +345,7 @@ const Checkout = () => {
value: expedisi.id,
label: expedisi.name,
carrierId: expedisi.deliveryCarrierId,
+ logo: expedisi.image,
}));
setExpedisi(dataExpedisi);
};
@@ -381,70 +431,71 @@ 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);
@@ -472,7 +523,7 @@ const Checkout = () => {
});
return;
}
- if (selectedExpedisi === 0) {
+ if (selectedCourier === 0 || !selectedCourier) {
setCheckoutValidation(true);
if (expedisiValidation.current) {
const position = expedisiValidation.current.getBoundingClientRect();
@@ -483,7 +534,16 @@ const Checkout = () => {
}
return;
}
- if (selectedCarrier != 1 && biayaKirim == 0) {
+ //new release
+ // if (selectedCarrier != 1 && biayaKirim == 0) {
+ // toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.');
+ // return;
+ // }
+ // 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;
}
@@ -493,17 +553,26 @@ const Checkout = () => {
quantity: product.quantity,
available_quantity: product?.availableQuantity,
}));
+ let estimated_courier = etd.split('-').map(Number);
+ let eta_courier = Math.max(...estimated_courier);
+ let eta_courier_start = Math.min(...estimated_courier);
+
let data = {
- // partner_shipping_id: auth.partnerId,
+ // partner_shipping_id: auth.partnerId,,
// partner_invoice_id: auth.partnerId,
partner_shipping_id: selectedAddress?.shipping?.id || auth.partnerId,
partner_invoice_id: selectedAddress?.invoicing?.id || auth.partnerId,
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: selectedCourierId,
+ estimated_arrival_days_start : parseInt(eta_courier_start) + parseInt(productSla),
+ estimated_arrival_days: parseInt(eta_courier) + parseInt(productSla),
+ delivery_service_type: selectedService?.service_type,
+ // New release
+ // carrier_id: selectedCarrierId,
+ // estimated_arrival_days: splitDuration(etd),
+ // delivery_service_type: selectedExpedisiService,
flash_sale: hasFlashSale, // dibuat negasi untuk ngetest kebalikan nilai false
voucher: activeVoucher,
voucher_shipping: activeVoucherShipping,
@@ -1160,20 +1229,21 @@ const Checkout = () => {
)}
<Divider />
<SectionValidation address={selectedAddress.shipping} />
- <SectionExpedisi
- address={selectedAddress.shipping}
- listExpedisi={listExpedisi}
- setSelectedExpedisi={setSelectedExpedisi}
- checkWeigth={checkWeigth}
- checkoutValidation={checkoutValidation}
- expedisiValidation={expedisiValidation}
- loadingRajaOngkir={loadingRajaOngkir}
- />
- <Divider />
- <SectionListService
- listserviceExpedisi={listserviceExpedisi}
- setSelectedServiceType={setSelectedServiceType}
- />
+ {/*new-relase*/}
+ {/*<SectionExpedisi*/}
+ {/* address={selectedAddress.shipping}*/}
+ {/* listExpedisi={listExpedisi}*/}
+ {/* setSelectedExpedisi={setSelectedExpedisi}*/}
+ {/* checkWeigth={checkWeigth}*/}
+ {/* checkoutValidation={checkoutValidation}*/}
+ {/* expedisiValidation={expedisiValidation}*/}
+ {/* loadingRajaOngkir={loadingRajaOngkir}*/}
+ {/* />*/}
+ {/* <Divider />*/}
+ {/* <SectionListService*/}
+ {/* listserviceExpedisi={listserviceExpedisi}*/}
+ {/* setSelectedServiceType={setSelectedServiceType}*/}
+ {/* />*/}
<div className='p-4 flex flex-col gap-y-4'>
{!!products &&
@@ -1262,7 +1332,10 @@ 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, productSla)}
+ </p>
</div>
<div>
{currencyFormat(
@@ -1386,7 +1459,8 @@ const Checkout = () => {
className='flex-1 btn-yellow'
onClick={checkout}
disabled={
- isLoading ||
+ //new release
+ // isLoading ||
!products ||
products?.length == 0 ||
priceCheck ||
@@ -1458,9 +1532,10 @@ const Checkout = () => {
/>
</Skeleton>
)}
+ {products && <SectionExpedition products={products} />}
<Divider />
<SectionValidation address={selectedAddress.shipping} />
- <SectionExpedisi
+ {/* <SectionExpedisi
address={selectedAddress.shipping}
listExpedisi={listExpedisi}
setSelectedExpedisi={setSelectedExpedisi}
@@ -1473,7 +1548,7 @@ const Checkout = () => {
<SectionListService
listserviceExpedisi={listserviceExpedisi}
setSelectedServiceType={setSelectedServiceType}
- />
+ /> */}
<div className='p-4'>
<div className='font-medium mb-6'>Detail Pesanan</div>
@@ -1569,7 +1644,9 @@ 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, productSla)}
+ </p>
</div>
<div>
{currencyFormat(
@@ -1691,7 +1768,8 @@ const Checkout = () => {
className='w-full btn-yellow mt-4'
onClick={checkout}
disabled={
- isLoading ||
+ // new-relase
+ // isLoading ||
!products ||
products?.length == 0 ||
priceCheck ||
@@ -1740,14 +1818,32 @@ const SectionAddress = ({ address, label, url }) => (
<p className='mt-1 text-gray_r-11'>
{address.street}, {address?.city?.name}
</p>
+ <div className='flex gap-x-2 items-center mt-4 cursor-pointer'>
+ <MapPinIcon
+ className={
+ address.addressMap
+ ? `h-6 w-6 text-gray-500`
+ : `h-6 w-6 text-red-500`
+ }
+ />
+ {address.addressMap ? (
+ <label>Sudah Pinpoint</label>
+ ) : (
+ <Link href={'/my/address/' + address.id + '/edit'} target='_blank' className='cursor-pointer'>
+ <label className='text-red-500 cursor-pointer '>Belum Pinpoint</label>
+ </Link>
+ )}
+ </div>
</div>
)}
</div>
);
const SectionValidation = ({ address }) =>
- address?.stateId == 0 ||
- (address?.rajaongkirCityId == 0 && (
+ //new release
+ // address?.stateId == 0 ||
+ // (address?.rajaongkirCityId == 0 && (
+ address?.stateId == 0 && (
<BottomPopup active={true} title='Update Alamat'>
<div className='leading-7 text-gray_r-12/80'>
Mohon untuk memperbarui alamat Anda dengan mengklik tombol di bawah ini.{' '}
@@ -1761,7 +1857,9 @@ const SectionValidation = ({ address }) =>
</Link>
</div>
</BottomPopup>
- ));
+ )
+// )
+;
const SectionExpedisi = ({
address,
diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx
new file mode 100644
index 00000000..40084048
--- /dev/null
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -0,0 +1,503 @@
+import { Skeleton, Spinner } from '@chakra-ui/react';
+import axios from 'axios';
+import { AnimatePresence, motion } from 'framer-motion';
+import React, { useEffect, useRef, useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { useQuery } from 'react-query';
+import { useAddress } from '../stores/useAdress';
+
+import currencyFormat from '@/core/utils/currencyFormat';
+import { useCheckout } from '../stores/stateCheckout';
+import { formatShipmentRange } from '../utils/functionCheckouit';
+import Image from 'next/image';
+import toast from 'react-hot-toast';
+
+import odooApi from '@/core/api/odooApi';
+import { getProductsSla } from '../api/checkoutApi';
+
+function mappingItems(products) {
+ return products?.map((item) => ({
+ name: item.parent.name,
+ description: `${item.code} - ${item.name}`,
+ value: item.price.priceDiscount,
+ weight: item.weight * 1000,
+ quantity: item.quantity,
+ }));
+}
+
+function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
+ // Buat peta courier berdasarkan nama courier dari couriers
+ 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;
+ }, {});
+
+ // Iterasi berdasarkan couriersOdoo
+ 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,
+ },
+ };
+ });
+}
+
+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_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())
+ ) {
+ 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_range: item.shipment_duration_range,
+ shipment_unit: item.shipment_duration_unit,
+ price: item.price,
+ service_type: item.service_type,
+ description: item.description,
+ },
+ },
+ };
+ } else {
+ 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,
+ description: item.description,
+ };
+ }
+
+ return result;
+ }, {});
+}
+
+// interface CourierService {
+// courier_name: string;
+// courier_code: string;
+// service_type: {
+// [key: string]: {
+// service_name: string;
+// duration: number;
+// shipment_duration: number;
+// price: number;
+// service_type: string;
+// description: string;
+// };
+// };
+// }
+
+// interface ServiceOption {
+// service_name: string;
+// duration: number;
+// shipment_duration: number;
+// price: number;
+// service_type: string;
+// description: string;
+// }
+
+export default function SectionExpedition({ 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,
+ } = useCheckout();
+
+ 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 expedition rates:', error);
+ }
+ };
+
+ useEffect(() => {
+ fetchSlaProducts();
+ }, []);
+
+ useEffect(() => {
+ if (slaProducts) {
+ let productSla = slaProducts?.slaTotal;
+ if (slaProducts.slaUnit === 'jam') {
+ productSla = 1;
+ }
+ setProductSla(productSla);
+ }
+ }, [slaProducts]);
+
+ const fetchExpedition = async () => {
+ let 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: items,
+ };
+ try {
+ const response = await axios.get(`/api/biteship-service`, {
+ params: { body: JSON.stringify(body) },
+ });
+ return response;
+ } catch (error) {
+ console.error('Failed to fetch expedition rates:', error);
+ }
+ };
+
+ 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 = (code) => {
+ setIsOpen(false);
+ setOnFocuseSelectedCourier(false);
+ const courier = code;
+ 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 Anda Belum Melakukan Pengaturan PinPoint Alamat Pegiriman.'
+ );
+ } else {
+ toast.error(
+ 'Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'
+ );
+ }
+ setServiceOptions([]);
+ }
+ } else {
+ setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null);
+ setServiceOptions([]);
+ }
+ };
+
+ const handleOnFocuse = (value) => {
+ setOnFocuseSelectedCourier(!value);
+ setIsOpen(false);
+ };
+
+ 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 (
+ <form >
+ <div className='px-4 py-2'>
+ <div className='flex justify-between items-center'>
+ <div className='font-medium'>Pilih Ekspedisi: </div>
+ <div className='w-[350px] max'>
+ <div className='px-4 py-2'>
+ <div className='flex justify-between items-center'>
+ <div className='w-[450px]'>
+ <div className='relative'>
+ {/* Custom Select Input Field */}
+ <div
+ className='w-full p-2 border rounded-lg bg-white cursor-pointer'
+ onClick={() => handleOnFocuse(onFocusSelectedCourier)}
+ >
+ {selectedCourier ? (
+ <div className='flex justify-between'>
+ <span>{selectedCourier}</span>
+ </div>
+ ) : (
+ <span className='text-gray-500'>Pilih Expedisi</span>
+ )}
+ </div>
+
+ {/* Dropdown Options */}
+ {onFocusSelectedCourier && (
+ <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10 max-h-[200px] overflow-y-auto'>
+ {!isLoading ? (
+ <>
+ <div
+ key={32}
+ onClick={() => onCourierChange(32)}
+ className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+ >
+ <div>
+ <p className='font-semibold'>SELF PICKUP</p>
+ </div>
+ </div>
+ {couriers?.map((courier) => (
+ <div
+ key={courier?.courier?.courier_code}
+ onClick={() => onCourierChange(courier)}
+ className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+ >
+ <div>
+ <p className='font-semibold'>
+ {courier?.label}
+ </p>
+ </div>
+ <span className='font-semibold'>
+ <Image
+ src={courier?.logo}
+ alt={courier?.courier?.courier_name}
+ width={50}
+ height={50}
+ />
+ </span>
+ </div>
+ ))}
+ </>
+ ) : (
+ <>
+ <Skeleton height={40} containerClassName='w-full' />
+ <Skeleton height={40} containerClassName='w-full' />
+ </>
+ )}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ {checkoutValidation && (
+ <span className='text-sm text-red-500'>
+ *silahkan pilih expedisi
+ </span>
+ )}
+ </div>
+ <style jsx>{`
+ .shake {
+ animation: shake 0.4s ease-in-out;
+ }
+ `}</style>
+ </div>
+ {checkWeigth == true && (
+ <p className='mt-4 text-gray_r-11 leading-6'>
+ Mohon maaf, pengiriman hanya tersedia untuk self pickup karena
+ terdapat barang yang belum diatur beratnya. Mohon atur berat barang
+ dengan menghubungi admin melalui{' '}
+ <a
+ className='text-danger-500 inline'
+ href='https://api.whatsapp.com/send?phone=6281717181922'
+ >
+ tautan ini
+ </a>
+ </p>
+ )}
+ </div>
+
+ {(serviceOptions.length > 0 ||
+ selectedService )&&
+ selectedCourier &&
+ selectedCourier !== 32 &&
+ selectedCourier !== 0 && (
+ <div className='px-4 py-2'>
+ <div className='flex justify-between items-center'>
+ <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
+ <div className='w-[350px]'>
+ <div className='relative'>
+ {/* Custom Select Input Field */}
+ <div
+ className='w-full p-2 border rounded-lg bg-white cursor-pointer'
+ onClick={() => setIsOpen(!isOpen)}
+ >
+ {selectedService ? (
+ <div className='flex justify-between'>
+ <span>{selectedService.service_name}</span>
+ <span className='font-semibold'>
+ {currencyFormat(
+ Math.round(
+ parseInt(selectedService?.price * 1.1) / 1000
+ ) * 1000
+ )}
+ </span>
+ </div>
+ ) : (
+ <span className='text-gray-500'>
+ Pilih layanan pengiriman
+ </span>
+ )}
+ </div>
+ {isOpen && (
+ <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10'>
+ {serviceOptions.map((service) => (
+ <div
+ key={service.service_type}
+ onClick={() => handleSelect(service)}
+ className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+ >
+ <div>
+ <p className='font-semibold'>
+ {service.service_name}
+ </p>
+ <p className='text-gray-600 text-sm'>
+ {formatShipmentRange(
+ service.shipment_range,
+ service.shipment_unit,
+ productSla
+ )}
+ </p>
+ </div>
+ <span className='font-semibold'>
+ {currencyFormat(
+ Math.round(
+ parseInt(service?.price * 1.1) / 1000
+ ) * 1000
+ )}
+ </span>
+ </div>
+ ))}
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ )}
+ </form>
+ );
+}