diff options
Diffstat (limited to 'src/lib/checkout/components/SectionExpedition.jsx')
| -rw-r--r-- | src/lib/checkout/components/SectionExpedition.jsx | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx new file mode 100644 index 00000000..ead65a6f --- /dev/null +++ b/src/lib/checkout/components/SectionExpedition.jsx @@ -0,0 +1,304 @@ +import React, { useEffect, useState } from 'react'; +import { useQuery } from 'react-query'; +import GetRatesCourierBiteship from '../api/getRatesCourier'; +import { useAddress } from '../stores/useAdress'; +import axios, { AxiosResponse } from 'axios'; +import { useForm, Controller } from 'react-hook-form'; +import { AnimatePresence, motion } from 'framer-motion'; +import { Spinner } from '@chakra-ui/react'; + +import currencyFormat from '@/core/utils/currencyFormat'; + +function mappingItems(products) { + return products?.map((item) => ({ + name: item.parent.name, + description: `${item.code} - ${item.name}`, + value: item.price.priceDiscount, + weight: item.weight, + quantity: item.quantity, + })); +} + +function mappingCourier(couriers) { + return couriers?.reduce((result, item) => { + const { courier_code, courier_service_code } = item; + + // 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, + service_type: { + [courier_service_code]: { + service_name: item.courier_service_name, + duration: item.duration, + shipment_duration: item.duration, + 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_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 { control, handleSubmit } = useForm(); + const [selectedCourier, setSelectedCourier] = useState(''); + const [serviceOptions, setServiceOptions] = useState([]); + const [selectedService, setSelectedService] = useState(null); + const [isOpen, setIsOpen] = useState(false); + + 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: 12440, + destination_postal_code: postalCode, + }; + } + + 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 fetchExpedition = async () => await GetRatesCourierBiteship({ destination, items }); + const { data, isLoading } = useQuery( + ['expedition', JSON.stringify(destination), JSON.stringify(items)], + fetchExpedition, + { + enabled: Boolean(Object.keys(destination).length) && items?.length > 0, + staleTime: Infinity, + cacheTime: Infinity, + } + ); + + const couriers = mappingCourier(data?.data?.pricing); + + console.log('couriers', couriers); + + const onCourierChange = (e) => { + const courier = e.target.value; + console.log('courier', courier); + setSelectedCourier(courier); + // Menentukan layanan berdasarkan pengiriman yang dipilih + if (courier && couriers[courier]) { + setServiceOptions(Object.values(couriers[courier]?.service_type)); + } else { + setServiceOptions([]); + } + }; + + const onSubmit = (data) => { + console.log(data); + }; + + const handleSelect = (service) => { + setSelectedService(service); + setIsOpen(false); + }; + + return ( + <form onSubmit={handleSubmit(onSubmit)}> + {/* Dropdown untuk memilih jenis pengiriman */} + <div className='px-4 py-2'> + <div className='flex justify-between items-center'> + <div className='font-medium'>Pilih Ekspedisi: </div> + <div className='w-[250px]'> + <div className='flex items-center gap-x-4'> + <select + className={`form-input `} + onChange={onCourierChange} + required + > + <option value='0,0'>Pilih Pengiriman</option> + <option value='1,32'>SELF PICKUP</option> + {couriers && + Object.values(couriers)?.map((expedisi) => ( + <option + value={expedisi.courier_code} + key={expedisi.courier_name} + > + {' '} + {expedisi.courier_name} + </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> + )} + </AnimatePresence> + </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> + + {selectedCourier && ( + <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(selectedService.price)} + </span> + </div> + ) : ( + <span className='text-gray-500'> + Pilih layanan pengiriman + </span> + )} + </div> + + {/* Dropdown Options */} + {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'> + Estimasi Tiba {service.duration} + </p> + </div> + <span className='font-semibold'>{currencyFormat(service.price)}</span> + </div> + ))} + </div> + )} + </div> + {/* <select + className='form-input' + // onChange={(e) => setSelectedServiceType(e.target.value)} + > + {serviceOptions.map( + (service: { service_name: string; service_type: string; duration: string, price: number }) => ( + <option + value={service?.service_type} + key={service.service_type} + > + <div className='flex items-center gap-x-4'> + <div> + <label>{service?.service_name}</label> + <span> Estimasi Tiba {service?.duration} </span> + </div> + <div> + <label>{service.price}</label> + </div> + </div> + </option> + ) + )} + </select> */} + </div> + </div> + </div> + )} + </form> + ); +} |
