|
|
@@ -1,15 +1,17 @@
|
|
|
"use client";
|
|
|
|
|
|
import {type Ref, useState, useEffect, useCallback, useImperativeHandle, useMemo } from "react";
|
|
|
+import clsx from "clsx";
|
|
|
import { useRouter } from 'next/navigation';
|
|
|
import { useForm, FormProvider } from "react-hook-form";
|
|
|
import { useCustomToast } from "@/utils/hooks/useToast";
|
|
|
-import {useCheckoutAddress} from "@/utils/hooks/useCheckoutAddress"
|
|
|
+import {useCheckoutAddress, addressIsSame} from "@/utils/hooks/useCheckoutAddress"
|
|
|
import {useLoginModal} from "@/providers/LoginModalProvider";
|
|
|
import { useGetCustomerAddress } from "@utils/hooks/useGetCustomerAddress";
|
|
|
import { EMAIL_REGEX } from "@utils/constants";
|
|
|
import type {
|
|
|
ShipAddressFormData,
|
|
|
+ BillAddressFormData,
|
|
|
FullAddressFormData,
|
|
|
CreateCheckoutAddressVariables,
|
|
|
} from "@/types/checkout/type";
|
|
|
@@ -20,11 +22,8 @@ import {clientFetch} from "@/lib/restApiClient";
|
|
|
import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
|
|
|
import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
|
|
|
import {normalizePhoneForForm} from "@/utils/phoneNumberTools";
|
|
|
-import AddressResultDisplay from "./AddressResultDisplay";
|
|
|
import ShippingAddressCheckout from "./ShippingAddressCheckout";
|
|
|
import BillingAddressCheckout from "./BillingAddressCheckout";
|
|
|
-import CommonModal from "@/components/theme/ui/CommonModal";
|
|
|
-
|
|
|
|
|
|
|
|
|
export interface RefCheckoutAddressHandle {
|
|
|
@@ -41,50 +40,44 @@ export interface RefCheckoutAddressHandle {
|
|
|
/**
|
|
|
* 地址表单默认值
|
|
|
*/
|
|
|
-function getBillingAddressFormData(billingAddress:CartAddress) {
|
|
|
- const billingCountry = billingAddress.country || 'US';
|
|
|
- const billingPhoneNumber = normalizePhoneForForm(billingAddress.phone, billingCountry) || "";
|
|
|
- const res = {
|
|
|
- "billingAddressId": billingAddress.id,
|
|
|
- "billingEmail": billingAddress.email,
|
|
|
- "billingFirstName": billingAddress.firstName,
|
|
|
- "billingLastName": billingAddress.lastName,
|
|
|
+function getBillingAddressFormData(billingAddress:CartAddress|null) {
|
|
|
+ let res:Omit<BillAddressFormData,'billingSameAsShipping'> = {
|
|
|
+ "billingAddressId": "",
|
|
|
+ "billingEmail": '',
|
|
|
+ "billingFirstName": "",
|
|
|
+ "billingLastName": "",
|
|
|
"billingCompanyName": "",
|
|
|
- "billingAddress": billingAddress.address,
|
|
|
- "billingCountry": billingCountry,
|
|
|
- "billingState": billingAddress.state,
|
|
|
- "billingCity": billingAddress.city,
|
|
|
- "billingPostcode": billingAddress.postcode,
|
|
|
- "billingPhoneNumber": billingPhoneNumber,
|
|
|
- };
|
|
|
-
|
|
|
- return res;
|
|
|
-}
|
|
|
-function getShippingAddressFormData(shippingAddress:CartAddress) {
|
|
|
- const shippingCountry = shippingAddress.country || 'US';
|
|
|
- const shippingPhoneNumber = normalizePhoneForForm(shippingAddress.phone, shippingCountry) || "";
|
|
|
- const res = {
|
|
|
- "shippingAddressId": shippingAddress.id,
|
|
|
- "shippingEmail": shippingAddress.email,
|
|
|
- "shippingFirstName": shippingAddress.firstName,
|
|
|
- "shippingLastName": shippingAddress.lastName,
|
|
|
- "shippingCompanyName": "",
|
|
|
- "shippingAddress": shippingAddress.address,
|
|
|
- "shippingCountry": shippingCountry,
|
|
|
- "shippingState": shippingAddress.state,
|
|
|
- "shippingCity": shippingAddress.city,
|
|
|
- "shippingPostcode": shippingAddress.postcode,
|
|
|
- "shippingPhoneNumber": shippingPhoneNumber,
|
|
|
+ "billingAddress": "",
|
|
|
+ "billingCountry": "US",
|
|
|
+ "billingState": "",
|
|
|
+ "billingCity": "",
|
|
|
+ "billingPostcode": "",
|
|
|
+ "billingPhoneNumber": "",
|
|
|
};
|
|
|
+ if(billingAddress) {
|
|
|
+ const billingCountry = billingAddress.country || 'US';
|
|
|
+ const billingPhoneNumber = normalizePhoneForForm(billingAddress.phone, billingCountry) || "";
|
|
|
+ res = {
|
|
|
+ "billingAddressId": billingAddress.id,
|
|
|
+ "billingEmail": billingAddress.email,
|
|
|
+ "billingFirstName": billingAddress.firstName,
|
|
|
+ "billingLastName": billingAddress.lastName,
|
|
|
+ "billingCompanyName": "",
|
|
|
+ "billingAddress": billingAddress.address,
|
|
|
+ "billingCountry": billingCountry,
|
|
|
+ "billingState": billingAddress.state,
|
|
|
+ "billingCity": billingAddress.city,
|
|
|
+ "billingPostcode": billingAddress.postcode,
|
|
|
+ "billingPhoneNumber": billingPhoneNumber,
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
return res;
|
|
|
}
|
|
|
-function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string) {
|
|
|
- const shippingAddress = cartDetail.shippingAddress;
|
|
|
- const billingAddress = cartDetail.billingAddress;
|
|
|
- const defaultValues = {
|
|
|
+function getShippingAddressFormData(shippingAddress:CartAddress|null) {
|
|
|
+ let res: ShipAddressFormData = {
|
|
|
"shippingAddressId": "",
|
|
|
- "shippingEmail": loginEmail ?? '',
|
|
|
+ "shippingEmail": "",
|
|
|
"shippingFirstName": "",
|
|
|
"shippingLastName": "",
|
|
|
"shippingCompanyName": "",
|
|
|
@@ -93,62 +86,45 @@ function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string)
|
|
|
"shippingState": "",
|
|
|
"shippingCity": "",
|
|
|
"shippingPostcode": "",
|
|
|
- "shippingPhoneNumber": "",
|
|
|
- "billingAddressId": "",
|
|
|
- "billingEmail": loginEmail ?? '',
|
|
|
- "billingFirstName": "",
|
|
|
- "billingLastName": "",
|
|
|
- "billingCompanyName": "",
|
|
|
- "billingAddress": "",
|
|
|
- "billingCountry": "US",
|
|
|
- "billingState": "",
|
|
|
- "billingCity": "",
|
|
|
- "billingPostcode": "",
|
|
|
- "billingPhoneNumber": "",
|
|
|
- "billingSameAsShipping": true
|
|
|
+ "shippingPhoneNumber": ""
|
|
|
+ };
|
|
|
+ if(shippingAddress) {
|
|
|
+ const shippingCountry = shippingAddress.country || 'US';
|
|
|
+ const shippingPhoneNumber = normalizePhoneForForm(shippingAddress.phone, shippingCountry) || "";
|
|
|
+ res = {
|
|
|
+ "shippingAddressId": shippingAddress.id,
|
|
|
+ "shippingEmail": shippingAddress.email,
|
|
|
+ "shippingFirstName": shippingAddress.firstName,
|
|
|
+ "shippingLastName": shippingAddress.lastName,
|
|
|
+ "shippingCompanyName": "",
|
|
|
+ "shippingAddress": shippingAddress.address,
|
|
|
+ "shippingCountry": shippingCountry,
|
|
|
+ "shippingState": shippingAddress.state,
|
|
|
+ "shippingCity": shippingAddress.city,
|
|
|
+ "shippingPostcode": shippingAddress.postcode,
|
|
|
+ "shippingPhoneNumber": shippingPhoneNumber,
|
|
|
+ };
|
|
|
}
|
|
|
- if(billingAddress) {
|
|
|
- const bs = getBillingAddressFormData(billingAddress);
|
|
|
- defaultValues.billingAddressId = bs.billingAddressId;
|
|
|
- defaultValues.billingEmail = bs.billingEmail;
|
|
|
- defaultValues.billingFirstName = bs.billingFirstName;
|
|
|
- defaultValues.billingLastName = bs.billingLastName;
|
|
|
- defaultValues.billingCompanyName = bs.billingCompanyName;
|
|
|
- defaultValues.billingAddress = bs.billingAddress;
|
|
|
- defaultValues.billingCountry = bs.billingCountry;
|
|
|
- defaultValues.billingState = bs.billingState;
|
|
|
- defaultValues.billingCity = bs.billingCity;
|
|
|
- defaultValues.billingPostcode = bs.billingPostcode;
|
|
|
- defaultValues.billingPhoneNumber = bs.billingPhoneNumber;
|
|
|
- // defaultValues.billingSameAsShipping = true;
|
|
|
+
|
|
|
+ return res;
|
|
|
+}
|
|
|
+function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string) {
|
|
|
+ const shippingAddress = cartDetail.shippingAddress;
|
|
|
+ const billingAddress = cartDetail.billingAddress;
|
|
|
+ const bs = getBillingAddressFormData(billingAddress);
|
|
|
+ const ss = getShippingAddressFormData(shippingAddress);
|
|
|
+ if(loginEmail && !bs.billingEmail) {
|
|
|
+ bs.billingEmail = loginEmail;
|
|
|
}
|
|
|
- if(shippingAddress) {
|
|
|
- const ss = getShippingAddressFormData(shippingAddress);
|
|
|
- defaultValues.shippingAddressId = ss.shippingAddressId;
|
|
|
- defaultValues.shippingEmail = ss.shippingEmail;
|
|
|
- defaultValues.shippingFirstName = ss.shippingFirstName;
|
|
|
- defaultValues.shippingLastName = ss.shippingLastName;
|
|
|
- defaultValues.shippingCompanyName = ss.shippingCompanyName;
|
|
|
- defaultValues.shippingAddress = ss.shippingAddress;
|
|
|
- defaultValues.shippingCountry = ss.shippingCountry;
|
|
|
- defaultValues.shippingState = ss.shippingState;
|
|
|
- defaultValues.shippingCity = ss.shippingCity;
|
|
|
- defaultValues.shippingPostcode = ss.shippingPostcode;
|
|
|
- defaultValues.shippingPhoneNumber = ss.shippingPhoneNumber;
|
|
|
+ if(loginEmail && !ss.shippingEmail) {
|
|
|
+ ss.shippingEmail = loginEmail;
|
|
|
}
|
|
|
- if( defaultValues.billingEmail === defaultValues.shippingEmail &&
|
|
|
- defaultValues.billingFirstName === defaultValues.shippingFirstName &&
|
|
|
- defaultValues.billingLastName === defaultValues.shippingLastName &&
|
|
|
- defaultValues.billingCompanyName === defaultValues.shippingCompanyName &&
|
|
|
- defaultValues.billingAddress === defaultValues.shippingAddress &&
|
|
|
- defaultValues.billingCountry === defaultValues.shippingCountry &&
|
|
|
- defaultValues.billingState === defaultValues.shippingState &&
|
|
|
- defaultValues.billingCity === defaultValues.shippingCity &&
|
|
|
- defaultValues.billingPostcode === defaultValues.shippingPostcode &&
|
|
|
- defaultValues.billingPhoneNumber === defaultValues.shippingPhoneNumber
|
|
|
- ) {
|
|
|
- defaultValues.billingSameAsShipping = true;
|
|
|
+ const defaultValues: FullAddressFormData = {
|
|
|
+ ...ss,
|
|
|
+ ...bs,
|
|
|
+ "billingSameAsShipping": addressIsSame(bs,ss)
|
|
|
}
|
|
|
+
|
|
|
return defaultValues;
|
|
|
}
|
|
|
/**
|
|
|
@@ -240,7 +216,6 @@ export function CheckoutAddress({
|
|
|
const [myAddressList, setMyAddressList] = useState<CustomerAddressItem[]>([]);
|
|
|
const [showShipFormField, setShowShipFormField] = useState(false);
|
|
|
const [showBillFormField, setShowBillFormField] = useState(false);
|
|
|
- const [addressFormModalOpen, setAddressFormModalOpen] = useState(false);
|
|
|
|
|
|
|
|
|
useImperativeHandle(ref, () => {
|
|
|
@@ -267,25 +242,6 @@ export function CheckoutAddress({
|
|
|
},[]);
|
|
|
|
|
|
|
|
|
- const openAddressFormModal = () => {
|
|
|
- setAddressFormModalOpen(true);
|
|
|
- setShowShipFormField(false);
|
|
|
- setShowBillFormField(false);
|
|
|
- if(cartData.billingAddress && cartData.shippingAddress) {
|
|
|
- addressForm.reset({
|
|
|
- ...getAddressFormDataFromCart(cartData)
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- };
|
|
|
- const closeAddressFormModal = () => {
|
|
|
- setAddressFormModalOpen(false);
|
|
|
- setShowShipFormField(false);
|
|
|
- setShowBillFormField(false);
|
|
|
- // 重置表单
|
|
|
- addressForm.reset();
|
|
|
- };
|
|
|
const addressFormOnSubmit = async (formData: FullAddressFormData) => {
|
|
|
// console.log('addressFormOnSubmit ---- ',formData); return;
|
|
|
const saveAddressParam = generateSaveCheckoutAddressParam(formData);
|
|
|
@@ -305,11 +261,38 @@ export function CheckoutAddress({
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- addressForm.resetField('shippingAddressId',{
|
|
|
- defaultValue: createAddressData.shippingAddressId
|
|
|
- });
|
|
|
- addressForm.resetField('billingAddressId',{
|
|
|
- defaultValue: createAddressData.billingAddressId
|
|
|
+ const shipAddressAfterSave: ShipAddressFormData = {
|
|
|
+ shippingAddressId: createAddressData.shippingAddressId,
|
|
|
+ shippingEmail: createAddressData.shippingEmail,
|
|
|
+ shippingFirstName: createAddressData.shippingFirstName,
|
|
|
+ shippingLastName: createAddressData.shippingLastName,
|
|
|
+ shippingCompanyName: createAddressData.shippingCompanyName || '',
|
|
|
+ shippingAddress: createAddressData.shippingAddress,
|
|
|
+ shippingCountry: createAddressData.shippingCountry,
|
|
|
+ shippingState: createAddressData.shippingState,
|
|
|
+ shippingCity: createAddressData.shippingCity,
|
|
|
+ shippingPostcode: createAddressData.shippingPostcode,
|
|
|
+ shippingPhoneNumber: createAddressData.shippingPhoneNumber,
|
|
|
+ };
|
|
|
+ const billAddressAfterSave: Omit<BillAddressFormData,'billingSameAsShipping'> = {
|
|
|
+ billingAddressId: createAddressData.billingAddressId,
|
|
|
+ billingFirstName: createAddressData.billingFirstName,
|
|
|
+ billingLastName: createAddressData.billingLastName,
|
|
|
+ billingEmail: createAddressData.billingEmail,
|
|
|
+ billingCompanyName: createAddressData.billingCompanyName || '',
|
|
|
+ billingAddress: createAddressData.billingAddress,
|
|
|
+ billingCity: createAddressData.billingCity,
|
|
|
+ billingState: createAddressData.billingState,
|
|
|
+ billingCountry: createAddressData.billingCountry,
|
|
|
+ billingPostcode: createAddressData.billingPostcode,
|
|
|
+ billingPhoneNumber: createAddressData.billingPhoneNumber
|
|
|
+ };
|
|
|
+ // 重置表单,更新默认值
|
|
|
+ addressForm.reset({
|
|
|
+ ...shipAddressAfterSave,
|
|
|
+ ...billAddressAfterSave,
|
|
|
+ billingSameAsShipping: addressIsSame(billAddressAfterSave,shipAddressAfterSave)
|
|
|
+
|
|
|
});
|
|
|
|
|
|
|
|
|
@@ -343,11 +326,13 @@ export function CheckoutAddress({
|
|
|
billingAddress: newBillingAddress,
|
|
|
shippingAddress: newShippingAddress
|
|
|
});
|
|
|
+
|
|
|
+ showShipFormFieldChange(false);
|
|
|
+ showBillFormFieldChange(false);
|
|
|
|
|
|
} else {
|
|
|
showToast(saveRes.msg, 'danger');
|
|
|
}
|
|
|
- setAddressFormModalOpen(false);
|
|
|
} catch(err) {
|
|
|
// 错误处理
|
|
|
console.error("save address error", err);
|
|
|
@@ -436,6 +421,35 @@ export function CheckoutAddress({
|
|
|
|
|
|
};
|
|
|
|
|
|
+ const isBillSameAsShip = addressForm.watch("billingSameAsShipping");
|
|
|
+ const showSaveBtn = () => {
|
|
|
+ let res = false;
|
|
|
+ if(
|
|
|
+ (noShipAddress || noBillAddress) ||
|
|
|
+ (!isBillSameAsShip && noBillAddress) ||
|
|
|
+ showShipFormField || showBillFormField
|
|
|
+ ) {
|
|
|
+ res = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return res;
|
|
|
+ };
|
|
|
+ const showCancelBtn = () => {
|
|
|
+ let res = false;
|
|
|
+ if(
|
|
|
+ showShipFormField || showBillFormField
|
|
|
+ ) {
|
|
|
+ res = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return res;
|
|
|
+ };
|
|
|
+ const cancelHandler = () => {
|
|
|
+ showShipFormFieldChange(false);
|
|
|
+ showBillFormFieldChange(false);
|
|
|
+ // 重置表单
|
|
|
+ addressForm.reset();
|
|
|
+ };
|
|
|
// function tt() {
|
|
|
// const arr = [
|
|
|
// ['US','3803800217'],
|
|
|
@@ -456,56 +470,60 @@ export function CheckoutAddress({
|
|
|
// });
|
|
|
// }
|
|
|
return (<>
|
|
|
- <AddressResultDisplay shippingAddress={cartData.shippingAddress || null}
|
|
|
- onAddressModalOpenClick={openAddressFormModal}
|
|
|
- />
|
|
|
- <CommonModal
|
|
|
- isOpen={addressFormModalOpen}
|
|
|
- onClose={closeAddressFormModal}
|
|
|
- header={
|
|
|
- <div className="w-full box-border p-3.75 h-14.5 flex justify-between items-center">
|
|
|
- <span>Shipping Address</span>
|
|
|
- <button className="w-6 h-6" onClick={closeAddressFormModal}>
|
|
|
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- }
|
|
|
- body={
|
|
|
- <div className="box-border w-full h-full p-3.75">
|
|
|
- <div>
|
|
|
- <FormProvider {...addressForm}>
|
|
|
- <form>
|
|
|
- <ShippingAddressCheckout
|
|
|
- noAddress={noShipAddress}
|
|
|
- isGuest={cartData.isGuest}
|
|
|
- customerAddressList={myAddressList}
|
|
|
- showFormField={showShipFormField}
|
|
|
- onShowFormFieldChange={showShipFormFieldChange}
|
|
|
- onEmailChange={verifyEmailIsRegistered}
|
|
|
- />
|
|
|
- <BillingAddressCheckout
|
|
|
- noAddress={noBillAddress}
|
|
|
- isGuest={cartData.isGuest}
|
|
|
- customerAddressList={myAddressList}
|
|
|
- showFormField={showBillFormField}
|
|
|
- onShowFormFieldChange={showBillFormFieldChange}
|
|
|
- />
|
|
|
- </form>
|
|
|
- </FormProvider>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- footer={
|
|
|
- <div className="box-border w-full p-3.75">
|
|
|
- <button className="block flex justify-center items-center w-full h-12 bg-ly-green rounded-3xl text-white text-ly-16 font-bold"
|
|
|
- onClick={addressForm.handleSubmit(addressFormOnSubmit)}
|
|
|
- >
|
|
|
- Save
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- }
|
|
|
- />
|
|
|
-
|
|
|
|
|
|
+
|
|
|
+ <div >
|
|
|
+ <FormProvider {...addressForm}>
|
|
|
+ <form>
|
|
|
+ <ShippingAddressCheckout
|
|
|
+ noAddress={noShipAddress}
|
|
|
+ isGuest={cartData.isGuest}
|
|
|
+ customerAddressList={myAddressList}
|
|
|
+ showFormField={showShipFormField}
|
|
|
+ onShowFormFieldChange={showShipFormFieldChange}
|
|
|
+ onEmailChange={verifyEmailIsRegistered}
|
|
|
+ />
|
|
|
+ <BillingAddressCheckout
|
|
|
+ noAddress={noBillAddress}
|
|
|
+ isGuest={cartData.isGuest}
|
|
|
+ customerAddressList={myAddressList}
|
|
|
+ showFormField={showBillFormField}
|
|
|
+ onShowFormFieldChange={showBillFormFieldChange}
|
|
|
+ />
|
|
|
+ </form>
|
|
|
+ </FormProvider>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ {/**
|
|
|
+ * save 按钮
|
|
|
+ * noShipAddress || noBillAddress 显示
|
|
|
+ * billingSameAsShipping是false && noBillAddress 显示
|
|
|
+ * change shipping address 显示
|
|
|
+ * change billing address 显示
|
|
|
+ *
|
|
|
+ * cancel 按钮
|
|
|
+ * change shipping address 显示
|
|
|
+ * change billing address 显示
|
|
|
+ */}
|
|
|
+ <div className="box-border w-full">
|
|
|
+ <button className={clsx("justify-center items-center w-full h-12 mt-4 bg-ly-green rounded-3xl text-white text-ly-16 font-bold",
|
|
|
+ showSaveBtn() ? 'flex' : 'hidden'
|
|
|
+ )}
|
|
|
+ type="button"
|
|
|
+ onClick={addressForm.handleSubmit(addressFormOnSubmit)}
|
|
|
+ >
|
|
|
+ Save
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <button className={clsx("flex justify-center items-center w-full h-12 mt-3 border-1 rounded-3xl text-ly-16 font-bold",
|
|
|
+ showCancelBtn() ? 'flex' : 'hidden'
|
|
|
+ )}
|
|
|
+ type="button"
|
|
|
+ onClick={cancelHandler}
|
|
|
+ >
|
|
|
+ Cancel
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</>);
|
|
|
};
|