"use client"; import {useState, useRef, useEffect, useCallback } from "react"; import clsx from "clsx"; import { useCustomToast } from "@/utils/hooks/useToast"; import {useCheckoutPaymentMethod} from "@/utils/hooks/useCheckoutPaymentMethod"; import {useCheckoutShippingMethod} from "@/utils/hooks/useCheckoutShippingMethod"; import { useAppDispatch } from "@/store/hooks"; import { updateCart, clearCart } from "@/store/slices/cart-slice"; import {useSaveCheckoutCart} from "@/utils/hooks/useSaveCheckoutCart"; import { usePlaceOrder } from "@/utils/hooks/usePlaceOrder"; import {usePaymentSDKContext} from "@/providers/PaymentSDKProvider"; import {airwallexManager} from "@/lib/Airwallex/useAirwallexCard"; import { PlaceOrderResult, PlaceOrderFunction, CreatePaymentInitiateVariables } from "@/types/checkout/type"; import { CartDetail,CartAddress } from "@/types/cart/type"; import { formatCartDetail } from "@/utils/cartDetailTools"; import { overlayLoading } from "@/components/theme/ui/kernel/loading/api"; import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api"; import {ShippingMethodCheckout,RefShippingMethodsHandle} from "./ShippingMethodCheckout"; import {PaymentMethodCheckout,RefPaymentMethodsHandle} from "./PaymentMethodCheckout"; import LoadingPaymentMethod from "./LoadingPaymentMethod"; import {CheckoutAddress, RefCheckoutAddressHandle} from "./CheckoutAddress/CheckoutAssress"; import LoadingCheckoutPlaceOrder from "./LoadingCheckoutPlaceOrder"; import CheckoutPlaceOrder from "./CheckoutPlaceOrder"; import PaypalApplepayButton from "./PaymentButton/PaypalApplepayButton"; import CheckoutGiftCardGate from "./GiftCard/CheckoutGiftCardGate"; import PromotionsDetails from "./PromotionsDetails"; import CheckoutVipPlus from "./VipPlus/CheckoutVipPlus"; import CheckoutProducts from "./CheckoutProducts/CheckoutProducts"; import CheckoutCoupon from "./CheckoutCoupon/CheckoutCoupon"; /*** * 保存完地址之后要重新获取运输方式和支付方式 * 变更运输方式后重新获取支付方式 * @todo 购物车为空 跳转到空购物车页面 */ export default function CheckoutWrapper({ loginEmail, cartDetailData, }: { loginEmail: string; cartDetailData: CartDetail; }) { const erudaCount = useRef(0); const {loadSdk} = usePaymentSDKContext(); const { createOrder } = usePlaceOrder(); const dispatch = useAppDispatch(); const [cartData, setCartData] = useState(cartDetailData); const {saveCheckoutCart} = useSaveCheckoutCart(); const { data: shippingMethodDatas, loading: shippingMethodLoading, error: shippingMethodError, getShippingMethod, } = useCheckoutShippingMethod(); const selectedPaymentMethod = cartData.paymentMethod || 'paypal_smart_button'; const selectedShippingRate = cartData.selectedShippingRate; const { data: paymentMethodDatas, loading: paymentMethodLoading, error: paymentMethodError, getPaymentMethod, } = useCheckoutPaymentMethod(); const { showToast } = useCustomToast(); const checkoutAddressRef = useRef(null); const methodShiippingRef = useRef(null); const methodPaymentRef = useRef(null); const changePaymentMethodToloadSdk = (method:string) => { if(method === 'klarna' || method === 'afterpay' || method === 'clearpay' || method === 'applepay' ) { loadSdk(method); } }; useEffect(() => { changePaymentMethodToloadSdk(selectedPaymentMethod); }, [selectedPaymentMethod]); const dispatchCartStore = useCallback((action: "clear" | "update", payload?:Partial) => { if(action === "clear") { dispatch(clearCart()); } else if(action === "update" && payload) { dispatch(updateCart(payload)); } },[dispatch]); const saveAddressCallback = async (resData: {billingAddress: CartAddress; shippingAddress: CartAddress;}) => { await Promise.all([getShippingMethod(),getPaymentMethod()]); dispatchCartStore('update',{ billingAddress: resData.billingAddress, shippingAddress: resData.shippingAddress }); setCartData(Object.assign({...cartData},{ billingAddress: resData.billingAddress, shippingAddress: resData.shippingAddress })); }; const handlePaymentMethodChange = async (method: string) => { changePaymentMethodToloadSdk(method); overlayLoading.start(); const saveRes = await saveCheckoutCart({ shippingMethod: '-1', paymentMethod: method, couponCode: '-1', giftCardNumber: '-1', memberDiscount: '-1' }); overlayLoading.stop(); if(!saveRes.error) { if(saveRes.data) { const newCartDetail = formatCartDetail(saveRes.data); dispatchCartStore('update',newCartDetail); setCartData({...newCartDetail}); } return true; } else { showToast(saveRes.msg, 'danger'); return false; } }; const handleShippingMethodChange = useCallback(async (method: string) => { overlayLoading.start(); const saveRes = await saveCheckoutCart({ shippingMethod: method, paymentMethod: '-1', couponCode: '-1', giftCardNumber: '-1', memberDiscount: '-1' }); overlayLoading.stop(); if(!saveRes.error) { if(saveRes.data) { const newCartDetail = formatCartDetail(saveRes.data); dispatchCartStore('update',newCartDetail); setCartData({...newCartDetail}); } // 保存成功之后需要重新获取支付方式 getPaymentMethod(); } else { showToast(saveRes.msg, 'danger'); } },[saveCheckoutCart,showToast,getPaymentMethod,dispatchCartStore]); // 校验地址 运输方式,支付方式; const validateCheckout = useCallback(async () => { if(checkoutAddressRef.current) { const addressValid = await checkoutAddressRef.current.validateAddressForm(); if(!addressValid) { showToast('Please check your address.', 'danger'); return false; } } else { showToast('Please wait for address form loading.', 'danger'); return false; } if(methodShiippingRef.current) { const shippingMethodValid = await methodShiippingRef.current.validateShipMethod(); if(!shippingMethodValid) { showToast('Please select a shipping method.', 'danger'); return false; } } else { showToast('Please wait for shipping method loading.', 'danger'); return false; } if(methodPaymentRef.current) { const paymentMethodValid = await methodPaymentRef.current.validatePaymentMethod(); const paymentMethod = methodPaymentRef.current.getSelectPaymentMethod(); if(!paymentMethodValid) { showToast('Please select a payment method.', 'danger'); return false; } if(paymentMethod === 'airwallex') { const airwallexCardValid = airwallexManager.validateCard(); if(airwallexCardValid.msg) { showToast(airwallexCardValid.msg,'danger'); } return airwallexCardValid.valid; } } else { showToast('Please wait for payment method loading.', 'danger'); return false; } if(!cartData) { showToast('Please add product to your cart.', 'danger'); return false; } //如果购物车详情没有保存过支付方式,则需要保存支付方式 if(cartData.paymentMethod === null) { const pmethod = methodPaymentRef.current.getSelectPaymentMethod(); const saveRes = await saveCheckoutCart({ shippingMethod: '-1', paymentMethod: pmethod, couponCode: '-1', giftCardNumber: '-1', memberDiscount: '-1' }); if(!saveRes.error) { if(saveRes.data) { const newCartDetail = formatCartDetail(saveRes.data); dispatchCartStore('update',newCartDetail); setCartData({...newCartDetail}); } } else { showToast(saveRes.msg, 'danger'); } } return true; },[showToast,saveCheckoutCart,dispatchCartStore]); // 苹果支付下单 const applepayPlaceOrder = useCallback(async () => { const res = await createOrder(); if(!res.error) { //创建订单成功后清空redux 购物车 dispatchCartStore('clear'); return { orderId: res.data?.gatewayOrderId ?? '', webOrderId: res.data?.orderId ?? '' }; } else{ // 抛出错误让第三方支付能够捕获 throw new Error("CREATE_ORDER_ERROR: " + res.msg); } },[createOrder,dispatchCartStore]); // 下单(下单和校验分开) const handlePlaceOrder: PlaceOrderFunction = async (params?: CreatePaymentInitiateVariables): Promise> => { const res = await createOrder(params); if(res.error) { overlayLoading.stop(); confirmDialog({ title: "Warning", content: res.msg + ". Create order failed. Please try again.", noCancel: true, }).then(() => {}); } else { //创建订单成功后清空redux 购物车 dispatchCartStore('clear'); } const pmethod = methodPaymentRef.current?.getSelectPaymentMethod(); let resultData: PlaceOrderResult; if(pmethod === 'airwallex') { const airCardNumber = airwallexManager.getCardNumberElement() as T; resultData = { data: res.data, otherData: airCardNumber }; } else if(pmethod === 'klarna') { const klaData = { billingAddress: cartData.billingAddress, shippingAddress: cartData.shippingAddress } as T; resultData = { data: res.data, otherData: klaData }; } else { resultData = { data: res.data, otherData: null }; } return resultData; } const onCartDataChange = async (paylod: CartDetail, dispatch: boolean = true) => { if(dispatch) { dispatchCartStore('update',paylod); } setCartData({...paylod}); // 还要请求支付方式和运输方式 await Promise.all([getShippingMethod(),getPaymentMethod()]); }; const testEruda = () => { erudaCount.current++ if(window.eruda && erudaCount.current > 10) { window.eruda.init(); } }; useEffect(() => { console.log('checkoutWrapper mout=========================='); return () => { console.log('checkoutWrapper unmout=========================='); } },[]); return (<>

Shipping Method

{!cartData.isGuest &&
}

Promotion Details

Payment Method

{ paymentMethodLoading && } { (!paymentMethodLoading && paymentMethodError) &&

{paymentMethodError}

} {(!paymentMethodLoading && !paymentMethodError) && }

By providing your information, you agree to Wiggins'sPrivacy Policyand Terms of Use.

{ paymentMethodLoading && }
); };