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.jsx121
-rw-r--r--src/lib/checkout/components/SectionExpedition.tsx248
2 files changed, 307 insertions, 62 deletions
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index e83e719c..b0f8f884 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -28,9 +28,12 @@ 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 { getVoucher } from '../api/getVoucher';
+import { useAddress } from '../stores/useAdress';
+import SectionExpedition from './SectionExpedition';
const SELF_PICKUP_ID = 32;
@@ -56,11 +59,15 @@ const Checkout = () => {
})
);
- 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;
@@ -90,10 +97,20 @@ 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);
@@ -268,58 +285,6 @@ const Checkout = () => {
};
}, []);
- const hitungDiscountVoucher = (code, source) => {
- let countDiscount = 0;
- if (source === 'voucher') {
- let dataVoucherIndex = listVouchers.findIndex(
- (voucher) => voucher.code == code
- );
- let dataActiveVoucher = listVouchers[dataVoucherIndex];
-
- countDiscount = dataActiveVoucher.discountVoucher;
- } else {
- let dataVoucherIndex = listVoucherShippings.findIndex(
- (voucher) => voucher.code == code
- );
- let dataActiveVoucher = listVoucherShippings[dataVoucherIndex];
-
- countDiscount = dataActiveVoucher.discountVoucher;
- }
-
- /*if (dataActiveVoucher.discountType === 'percentage') {
- countDiscount = cartCheckout?.subtotal * (dataActiveVoucher.discountAmount / 100)
- if (
- dataActiveVoucher.maxDiscountAmount > 0 &&
- countDiscount > dataActiveVoucher.maxDiscountAmount
- ) {
- countDiscount = dataActiveVoucher.maxDiscountAmount
- }
- } else {
- countDiscount = dataActiveVoucher.discountAmount
- }*/
-
- return countDiscount;
- };
-
- // useEffect(() => {
- // if (!listVouchers) return;
- // if (!activeVoucher) return;
-
- // console.log('voucher')
- // const countDiscount = hitungDiscountVoucher(activeVoucher, 'voucher');
-
- // SetDiscountVoucher(countDiscount);
- // }, [activeVoucher, listVouchers]);
-
- // useEffect(() => {
- // if (!listVoucherShippings) return;
- // if (!activeVoucherShipping) return;
-
- // const countDiscount = hitungDiscountVoucher(activeVoucherShipping, 'voucher_shipping');
-
- // SetDiscountVoucherOngkir(countDiscount);
- // }, [activeVoucherShipping, listVoucherShippings]);
-
useEffect(() => {
if (qVoucher === 'PASTIHEMAT' && listVouchers) {
let code = qVoucher;
@@ -413,7 +378,12 @@ const Checkout = () => {
Math.round(parseInt(finalShippingAmt * 1.1) / 1000) * 1000;
const finalGT = GT < 0 ? 0 : GT;
setGrandTotal(finalGT);
- }, [biayaKirim, cartCheckout?.grandTotal, activeVoucher, activeVoucherShipping]);
+ }, [
+ biayaKirim,
+ cartCheckout?.grandTotal,
+ activeVoucher,
+ activeVoucherShipping,
+ ]);
const checkout = async () => {
const file = poFile.current.files[0];
@@ -501,7 +471,7 @@ const Checkout = () => {
}
}
- /* const midtrans = async () => {
+ /* const midtrans = async () => {
for (const product of products) deleteItemCart({ productId: product.id });
if (grandTotal > 0) {
const payment = await axios.post(
@@ -1193,7 +1163,11 @@ const Checkout = () => {
<div className='text-gray_r-11'>
Biaya Kirim <p className='text-xs mt-1'>{etdFix}</p>
</div>
- <div>{currencyFormat(Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000)}</div>
+ <div>
+ {currencyFormat(
+ Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000
+ )}
+ </div>
</div>
{activeVoucherShipping && voucherShippingAmt && (
<div className='flex gap-x-2 justify-between'>
@@ -1383,6 +1357,7 @@ const Checkout = () => {
/>
</Skeleton>
)}
+ {products && <SectionExpedition products={products} />}
<Divider />
<SectionValidation address={selectedAddress.invoicing} />
<SectionExpedisi
@@ -1494,7 +1469,11 @@ const Checkout = () => {
Biaya Kirim
<p className='text-xs mt-1'>{etdFix}</p>
</div>
- <div>{currencyFormat(Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000) }</div>
+ <div>
+ {currencyFormat(
+ Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000
+ )}
+ </div>
</div>
{activeVoucherShipping && voucherShippingAmt && (
<div className='flex gap-x-2 justify-between'>
@@ -1659,6 +1638,20 @@ 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'>
+ <MapPinIcon
+ className={
+ address.addressMap
+ ? `h-6 w-6 text-gray-500`
+ : `h-6 w-6 text-red-500`
+ }
+ />
+ {address.addressMap ? (
+ <label>Sudah Pinpoint</label>
+ ) : (
+ <label className='text-red-500 '>Belum Pinpoint</label>
+ )}
+ </div>
</div>
)}
</div>
@@ -1681,6 +1674,10 @@ const SectionValidation = ({ address }) =>
</BottomPopup>
);
+const SectionExpedisiBiteship = ({ listExpedisi, setSelectedExpedisi }) => (
+ <></>
+);
+
const SectionExpedisi = ({
address,
listExpedisi,
diff --git a/src/lib/checkout/components/SectionExpedition.tsx b/src/lib/checkout/components/SectionExpedition.tsx
new file mode 100644
index 00000000..a6e05893
--- /dev/null
+++ b/src/lib/checkout/components/SectionExpedition.tsx
@@ -0,0 +1,248 @@
+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';
+
+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;
+ };
+ };
+}
+
+export default function SectionExpedition({ products }) {
+ const { addressMaps, coordinate, postalCode } = useAddress();
+ const { control, handleSubmit } = useForm();
+ const [selectedCourier, setSelectedCourier] = useState('');
+ const [serviceOptions, setServiceOptions] = useState([]);
+
+ 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: CourierService = 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([]);
+ }
+ };
+
+ console.log(
+ 'serviceOptions',
+ couriers[selectedCourier]?.service_type,
+ selectedCourier
+ );
+ const onSubmit = (data) => {
+ console.log(data);
+ };
+
+ 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-[250px]'>
+ <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>
+ );
+}