'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,ninja,lion,rara,sicepat,jnt,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 )}
))}
)}
)}
); }