import { Skeleton, Spinner } from '@chakra-ui/react';
import {
BanknotesIcon,
ChevronLeftIcon,
ClockIcon,
ExclamationCircleIcon,
} from '@heroicons/react/24/outline';
import axios from 'axios';
import { AnimatePresence, motion } from 'framer-motion';
import { useRouter } from 'next/router';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { toast } from 'react-hot-toast';
import { useQuery } from 'react-query';
import snakecaseKeys from 'snakecase-keys';
import Alert from '@/core/components/elements/Alert/Alert';
import Divider from '@/core/components/elements/Divider/Divider';
import Image from '@/core/components/elements/Image/Image';
import Link from '@/core/components/elements/Link/Link';
import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
import DesktopView from '@/core/components/views/DesktopView';
import MobileView from '@/core/components/views/MobileView';
import useAuth from '@/core/hooks/useAuth';
import { getItemAddress } from '@/core/utils/address';
import { deleteItemCart } from '@/core/utils/cart';
import currencyFormat from '@/core/utils/currencyFormat';
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');
const { getProductsCheckout } = require('../api/checkoutApi');
function convertToInternational(number) {
if (typeof number !== 'string') {
throw new Error('Input harus berupa string');
}
if (number.startsWith('08')) {
return '+62' + number.slice(2);
}
return number;
}
const Checkout = () => {
const PPN = process.env.NEXT_PUBLIC_PPN
? parseFloat(process.env.NEXT_PUBLIC_PPN)
: 0;
const router = useRouter();
const query = router.query.source ?? null;
const qVoucher = router.query.voucher ?? null;
const auth = useAuth();
const [activeVoucher, SetActiveVoucher] = useState(null);
const [activeVoucherShipping, setActiveVoucherShipping] = useState(null);
const { data: cartCheckout } = useQuery(
['cartCheckout', activeVoucher, activeVoucherShipping],
() =>
getProductsCheckout({
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,
addresses,
setAddresses,
setAddressMaps,
setCoordinate,
setPostalCode,
} = useAddress();
useEffect(() => {
if (!auth) return;
const getAddresses = async () => {
const dataAddresses = await addressesApi();
setAddresses(dataAddresses);
};
getAddresses();
}, [auth]);
useEffect(() => {
if (!addresses) return;
const matchAddress = (key) => {
if (key === 'invoicing') {
key = 'invoice';
}
const addressToMatch = getItemAddress(key);
const foundAddress = addresses.filter(
(address) => address.id == addressToMatch
);
if (foundAddress.length > 0) {
return foundAddress[0];
}
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 [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);
//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 [bottomPopup, SetBottomPopup] = useState(null);
const [bottomPopupTnC, SetBottomPopupTnC] = useState(null);
const [itemTnC, setItemTnC] = useState(null);
const [listVouchers, SetListVoucher] = useState(null);
const [listVoucherShippings, SetListVoucherShipping] = useState(null);
const [discountVoucher, SetDiscountVoucher] = useState(0);
const [codeVoucher, SetCodeVoucher] = useState(null);
const [findCodeVoucher, SetFindVoucher] = useState(null);
const [selisihHargaCode, SetSelisihHargaCode] = useState(null);
const [buttonTerapkan, SetButtonTerapkan] = 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 () => {
if (!listVouchers) {
try {
setLoadingVoucher(true);
const productCategories = products
?.reduce((categories, product) => {
if (product.categories && Array.isArray(product.categories)) {
product.categories.forEach((category) => {
if (category.id && !categories.includes(category.id)) {
categories.push(category.id);
}
});
}
return categories;
}, [])
.join(',');
let dataVoucher = await getVoucher(auth?.id, {
source: query,
type: 'all,brand',
partner_id: auth?.partnerId,
voucher_category: productCategories, // Add the product categories
});
SetListVoucher(dataVoucher);
let dataVoucherShipping = await getVoucher(auth?.id, {
source: query,
type: 'shipping',
voucher_category: productCategories, // Add the product categories
});
SetListVoucherShipping(dataVoucherShipping);
} finally {
setLoadingVoucher(false);
}
}
};
const VoucherCode = async (code) => {
const productCategories = products
?.reduce((categories, product) => {
if (product.categories && Array.isArray(product.categories)) {
product.categories.forEach((category) => {
if (category.id && !categories.includes(category.id)) {
categories.push(category.id);
}
});
}
return categories;
}, [])
.join(',');
let dataVoucher = await getVoucher(auth?.id, {
source: query,
code: code,
voucher_category: productCategories, // Add the product categories
});
if (dataVoucher.length <= 0) {
SetFindVoucher(1);
return;
}
dataVoucher.forEach((addNewLine) => {
if (addNewLine.applyType !== 'shipping') {
// Mencari voucher dalam listVouchers
let checkList = listVouchers?.findIndex(
(voucher) => voucher.code === addNewLine.code
);
if (checkList >= 0) {
if (listVouchers[checkList].canApply) {
ToggleSwitch(addNewLine.code); // Perbaikan: Gunakan code voucher yang benar
SetCodeVoucher(null);
} else {
SetSelisihHargaCode(listVouchers[checkList].differenceToApply);
SetFindVoucher(2);
}
return; // Hentikan eksekusi lebih lanjut pada iterasi ini
}
// Memeriksa apakah subtotal memenuhi syarat minimal pembelian
if (cartCheckout?.subtotal < addNewLine.minPurchaseAmount) {
SetSelisihHargaCode(
currencyFormat(
addNewLine.minPurchaseAmount - cartCheckout?.subtotal
)
);
SetFindVoucher(2);
return;
} else {
SetFindVoucher(3);
SetButtonTerapkan(true);
}
// Tambahkan voucher ke list dan set voucher aktif
SetListVoucher((prevList) => [addNewLine, ...prevList]);
if (addNewLine.canApply) {
SetActiveVoucher(addNewLine.code);
}
} else {
// Mencari voucher dalam listVoucherShippings
let checkList = listVoucherShippings?.findIndex(
(voucher) => voucher.code === addNewLine.code
);
if (checkList >= 0) {
if (listVoucherShippings[checkList].canApply) {
ToggleSwitch(addNewLine.code); // Perbaikan: Gunakan code voucher yang benar
SetCodeVoucher(null);
} else {
SetSelisihHargaCode(
listVoucherShippings[checkList].differenceToApply
);
SetFindVoucher(2);
}
return; // Hentikan eksekusi lebih lanjut pada iterasi ini
}
// Memeriksa apakah subtotal memenuhi syarat minimal pembelian
if (cartCheckout?.subtotal < addNewLine.minPurchaseAmount) {
SetSelisihHargaCode(
currencyFormat(
addNewLine.minPurchaseAmount - cartCheckout?.subtotal
)
);
SetFindVoucher(2);
return;
} else {
SetFindVoucher(3);
SetButtonTerapkan(true);
}
// Tambahkan voucher ke list pengiriman dan set voucher aktif pengiriman
SetListVoucherShipping((prevList) => [addNewLine, ...prevList]);
if (addNewLine.canApply) {
setActiveVoucherShipping(addNewLine.code);
}
}
});
// let addNewLine = dataVoucher[0];
};
useEffect(() => {
SetFindVoucher(null);
}, [bottomPopup]);
useEffect(() => {
// voucher();
const loadExpedisi = async () => {
let dataExpedisi = await ExpedisiList();
dataExpedisi = dataExpedisi.map((expedisi) => ({
value: expedisi.id,
label: expedisi.name,
carrierId: expedisi.deliveryCarrierId,
logo: expedisi.image,
}));
setExpedisi(dataExpedisi);
};
loadExpedisi();
const handlePopState = () => {
router.push('/shop/cart');
};
window.onpopstate = handlePopState;
return () => {
window.onpopstate = null;
};
}, []);
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;
VoucherCode(code);
}
}, [listVouchers]);
useEffect(() => {
setProducts(cartCheckout?.products);
setCheckWeight(cartCheckout?.hasProductWithoutWeight);
setTotalWeight(cartCheckout?.totalWeight.g);
const hasFlashSale = cartCheckout?.products.some(
(product) => product.hasFlashsale
);
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]);
//
const poNumber = useRef(null);
const poFile = useRef(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const GT =
cartCheckout?.grandTotal +
Math.round(parseInt(finalShippingAmt * 1.1) / 1000) * 1000;
const finalGT = GT < 0 ? 0 : GT;
setGrandTotal(finalGT);
}, [
biayaKirim,
cartCheckout?.grandTotal,
activeVoucher,
activeVoucherShipping,
]);
const checkout = async () => {
const file = poFile.current.files[0];
if (typeof file !== 'undefined' && file.size > 5000000) {
toast.error('Maksimal ukuran file adalah 5MB', {
position: 'bottom-center',
});
return;
}
if (selectedCourier === 0 || !selectedCourier) {
setCheckoutValidation(true);
if (expedisiValidation.current) {
const position = expedisiValidation.current.getBoundingClientRect();
window.scrollTo({
top: position.top - 300 + window.pageYOffset,
behavior: 'smooth',
});
}
return;
}
//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;
}
setIsLoading(true);
const productOrder = products.map((product) => ({
product_id: product.id,
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_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: selectedCourierId,
// estimated_arrival_days_start : parseInt(eta_courier_start) + parseInt(productSla),
// estimated_arrival_days: parseInt(eta_courier) + parseInt(productSla),
// If NaN conver to 0 (int)
estimated_arrival_days_start: (isNaN(parseInt(eta_courier_start)) ? 0 : parseInt(eta_courier_start)) +
(isNaN(parseInt(productSla)) ? 0 : parseInt(productSla)),
estimated_arrival_days: (isNaN(parseInt(eta_courier)) ? 0 : parseInt(eta_courier)) +
(isNaN(parseInt(productSla)) ? 0 : 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,
type: 'sale_order',
};
if (query) {
data.source = 'buy';
}
if (poNumber.current.value) {
if (typeof file == 'undefined') {
toast.error(
'Nomor PO ' +
poNumber.current.value +
' telah dimasukkan, Harap upload file PO yang dimaksud'
);
setIsLoading(false);
return;
}
data.po_number = poNumber.current.value;
}
if (typeof file !== 'undefined') data.po_file = await getFileBase64(file);
const isCheckouted = await checkoutApi({ data });
if (!isCheckouted?.id) {
toast.error('Gagal melakukan transaksi, terjadi kesalahan internal');
setIsLoading(false);
return;
} else {
gtagPurchase(products, biayaKirim, isCheckouted.name);
gtag('event', 'conversion', {
send_to: 'AW-954540379/nDymCL3BhaQYENvClMcD',
value:
cartCheckout?.grandTotal +
Math.round(parseInt(biayaKirim * 1.1) / 1000) * 1000,
currency: 'IDR',
transaction_id: isCheckouted.id,
});
gtag('set', 'user_data', {
email: auth.email,
phone_number:
convertToInternational(auth.mobile) ??
convertToInternational(auth.phone),
});
gtag('config', 'AW-954540379', { ' allow_enhanced_conversions': true });
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 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 () => {
VoucherCode(codeVoucher);
};
const handleUseVoucher = async (code, isCheck) => {
if (isCheck) {
if (code === activeVoucher) {
SetActiveVoucher(null);
SetDiscountVoucher(0);
} else {
SetActiveVoucher(code);
SetFindVoucher(null);
document.getElementById('uniqCode')
? (document.getElementById('uniqCode').value = '')
: '';
SetButtonTerapkan(false);
}
} else {
SetActiveVoucher(code);
SetFindVoucher(null);
document.getElementById('uniqCode')
? (document.getElementById('uniqCode').value = '')
: '';
SetButtonTerapkan(false);
}
};
const onChangeCodeVoucher = async (e) => {
SetCodeVoucher(e.target.value);
SetButtonTerapkan(false);
};
const [isChecked, setIsChecked] = useState(false);
const ToggleSwitch = (code) => {
setIsChecked(!isChecked);
handleUseVoucher(code, !isChecked);
};
const handlingTnC = async (item) => {
setItemTnC(item);
SetBottomPopupTnC(true);
};
const hasNoPrice = useMemo(() => {
if (!products) return false;
for (const item of products) {
if (item.price.priceDiscount == 0) return true;
}
return false;
}, [products]);
const voucherShippingAmt = cartCheckout?.discountVoucherShipping || 0;
const discShippingAmt = Math.min(biayaKirim, voucherShippingAmt);
const finalShippingAmt = biayaKirim - discShippingAmt;
const totalDiscountVoucher =
cartCheckout?.discountVoucher +
(cartCheckout?.discountVoucherShipping || 0);
return (
<>
Maaf, saat ini tidak ada voucher yang tersedia.
Potensi potongan sebesar{' '}
{currencyFormat(item.discountVoucher)}
Voucher tidak bisa di gunakan,{' '}
Baca Selengkapnya !
Kode Voucher :{' '}
{item.code}
{activeVoucher === item.code && (
Voucher digunakan{' '}
)}
Potensi potongan sebesar{' '}
{currencyFormat(item.discountVoucher)}
Voucher tidak bisa di gunakan,{' '}
Baca Selengkapnya !
Kode Voucher :{' '}
{item.code}
{activeVoucher === item.code && (
Voucher digunakan{' '}
)}
{formatShipmentRange(etd, unit, productSla)}
*) Belum termasuk biaya pengiriman
Dengan melakukan pembelian melalui website Indoteknik, saya
menyetujui{' '}
Syarat & Ketentuan
{' '}
yang berlaku
Ukuran dokumen PO Maksimal 5MB
{formatShipmentRange(etd, unit, productSla)}
Dengan melakukan pembelian melalui website Indoteknik, saya
menyetujui{' '}
Syarat & Ketentuan
{' '}
yang berlaku
Ukuran dokumen PO Maksimal 5MB
{itemTnC?.name}
Syarat dan Ketentuan
{/* {!loadingVoucher &&
listVouchers?.length === 1 &&
listVoucherShippings?.length === 1}
{
Tidak ada voucher tersedia
Promo Extra Potongan Ongkir
{listVoucherShippings?.map((item) => (
{item.name}
Promo Khusus Untuk {auth?.name}
)}
{loadingVoucher && (
<>
{item.name}
{!cartCheckout ? (
{!cartCheckout ? (
{!cartCheckout ? (
{!cartCheckout ? (
{priceCheck && (
{address.name}
{address.mobile}
{address.street}, {address?.city?.name}
Mohon maaf, pengiriman hanya tersedia untuk self pickup karena terdapat barang yang belum diatur beratnya. Mohon atur berat barang dengan menghubungi admin melalui{' '} tautan ini
)}Indoteknik
Jl. Bandengan Utara Raya No.85, RT.3/RW.16, Penjaringan, Kec. Penjaringan, Kota Jkt Utara, Daerah Khusus Ibukota Jakarta, Indonesia Kodepos : 14440
Telp : 021-2933 8828/29