2021-07-22 11:03:00 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import { __ } from '@wordpress/i18n';
|
2023-08-09 17:24:51 +00:00
|
|
|
import {
|
|
|
|
useMemo,
|
|
|
|
useEffect,
|
|
|
|
Fragment,
|
|
|
|
useState,
|
|
|
|
useCallback,
|
|
|
|
} from '@wordpress/element';
|
2021-07-22 11:03:00 +00:00
|
|
|
import { AddressForm } from '@woocommerce/base-components/cart-checkout';
|
|
|
|
import {
|
|
|
|
useCheckoutAddress,
|
|
|
|
useStoreEvents,
|
|
|
|
useEditorContext,
|
2022-12-19 15:30:13 +00:00
|
|
|
noticeContexts,
|
2021-07-22 11:03:00 +00:00
|
|
|
} from '@woocommerce/base-context';
|
2022-12-19 15:30:13 +00:00
|
|
|
import {
|
|
|
|
CheckboxControl,
|
|
|
|
StoreNoticesContainer,
|
|
|
|
} from '@woocommerce/blocks-checkout';
|
2021-11-26 14:47:37 +00:00
|
|
|
import Noninteractive from '@woocommerce/base-components/noninteractive';
|
2022-02-22 17:45:01 +00:00
|
|
|
import type {
|
|
|
|
BillingAddress,
|
|
|
|
ShippingAddress,
|
|
|
|
AddressField,
|
|
|
|
AddressFields,
|
|
|
|
} from '@woocommerce/settings';
|
2021-07-22 11:03:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import PhoneNumber from '../../phone-number';
|
|
|
|
|
|
|
|
const Block = ( {
|
|
|
|
showCompanyField = false,
|
|
|
|
showApartmentField = false,
|
|
|
|
showPhoneField = false,
|
|
|
|
requireCompanyField = false,
|
|
|
|
requirePhoneField = false,
|
|
|
|
}: {
|
|
|
|
showCompanyField: boolean;
|
|
|
|
showApartmentField: boolean;
|
|
|
|
showPhoneField: boolean;
|
|
|
|
requireCompanyField: boolean;
|
|
|
|
requirePhoneField: boolean;
|
|
|
|
} ): JSX.Element => {
|
|
|
|
const {
|
|
|
|
defaultAddressFields,
|
2022-02-22 17:45:01 +00:00
|
|
|
setShippingAddress,
|
2022-06-10 16:59:25 +00:00
|
|
|
setBillingAddress,
|
2022-02-22 17:45:01 +00:00
|
|
|
shippingAddress,
|
2023-05-03 13:45:57 +00:00
|
|
|
billingAddress,
|
2021-07-22 11:03:00 +00:00
|
|
|
setShippingPhone,
|
2022-02-22 17:45:01 +00:00
|
|
|
useShippingAsBilling,
|
|
|
|
setUseShippingAsBilling,
|
2021-07-22 11:03:00 +00:00
|
|
|
} = useCheckoutAddress();
|
|
|
|
const { dispatchCheckoutEvent } = useStoreEvents();
|
|
|
|
const { isEditor } = useEditorContext();
|
|
|
|
|
2023-05-03 13:45:57 +00:00
|
|
|
const { email } = billingAddress;
|
2022-07-28 14:38:29 +00:00
|
|
|
// This is used to track whether the "Use shipping as billing" checkbox was checked on first load and if we synced
|
|
|
|
// the shipping address to the billing address if it was. This is not used on further toggles of the checkbox.
|
|
|
|
const [ addressesSynced, setAddressesSynced ] = useState( false );
|
|
|
|
|
2021-07-22 11:03:00 +00:00
|
|
|
// Clears data if fields are hidden.
|
|
|
|
useEffect( () => {
|
|
|
|
if ( ! showPhoneField ) {
|
|
|
|
setShippingPhone( '' );
|
|
|
|
}
|
|
|
|
}, [ showPhoneField, setShippingPhone ] );
|
|
|
|
|
2022-07-28 14:38:29 +00:00
|
|
|
// Run this on first render to ensure addresses sync if needed, there is no need to re-run this when toggling the
|
|
|
|
// checkbox.
|
2023-05-03 13:45:57 +00:00
|
|
|
useEffect(
|
|
|
|
() => {
|
|
|
|
if ( addressesSynced ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( useShippingAsBilling ) {
|
|
|
|
setBillingAddress( { ...shippingAddress, email } );
|
|
|
|
}
|
|
|
|
setAddressesSynced( true );
|
|
|
|
},
|
|
|
|
// Skip the `email` dependency since we don't want to re-run if that changes, but we do want to sync it on first render.
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
[
|
|
|
|
addressesSynced,
|
|
|
|
setBillingAddress,
|
|
|
|
shippingAddress,
|
|
|
|
useShippingAsBilling,
|
|
|
|
]
|
|
|
|
);
|
2022-07-28 14:38:29 +00:00
|
|
|
|
2021-07-22 11:03:00 +00:00
|
|
|
const addressFieldsConfig = useMemo( () => {
|
|
|
|
return {
|
|
|
|
company: {
|
|
|
|
hidden: ! showCompanyField,
|
|
|
|
required: requireCompanyField,
|
|
|
|
},
|
|
|
|
address_2: {
|
|
|
|
hidden: ! showApartmentField,
|
|
|
|
},
|
|
|
|
};
|
2022-02-22 17:45:01 +00:00
|
|
|
}, [
|
|
|
|
showCompanyField,
|
|
|
|
requireCompanyField,
|
|
|
|
showApartmentField,
|
|
|
|
] ) as Record< keyof AddressFields, Partial< AddressField > >;
|
2021-07-22 11:03:00 +00:00
|
|
|
|
2023-08-09 17:24:51 +00:00
|
|
|
const onChangeAddress = useCallback(
|
|
|
|
( values: Partial< ShippingAddress > ) => {
|
|
|
|
setShippingAddress( values );
|
|
|
|
if ( useShippingAsBilling ) {
|
|
|
|
setBillingAddress( { ...values, email } );
|
|
|
|
dispatchCheckoutEvent( 'set-billing-address' );
|
|
|
|
}
|
|
|
|
dispatchCheckoutEvent( 'set-shipping-address' );
|
|
|
|
},
|
|
|
|
[
|
|
|
|
dispatchCheckoutEvent,
|
|
|
|
email,
|
|
|
|
setBillingAddress,
|
|
|
|
setShippingAddress,
|
|
|
|
useShippingAsBilling,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2021-11-26 14:47:37 +00:00
|
|
|
const AddressFormWrapperComponent = isEditor ? Noninteractive : Fragment;
|
2023-02-09 13:41:18 +00:00
|
|
|
const noticeContext = useShippingAsBilling
|
|
|
|
? [ noticeContexts.SHIPPING_ADDRESS, noticeContexts.BILLING_ADDRESS ]
|
|
|
|
: [ noticeContexts.SHIPPING_ADDRESS ];
|
2021-07-22 11:03:00 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<AddressFormWrapperComponent>
|
2023-02-09 13:41:18 +00:00
|
|
|
<StoreNoticesContainer context={ noticeContext } />
|
2021-07-22 11:03:00 +00:00
|
|
|
<AddressForm
|
|
|
|
id="shipping"
|
|
|
|
type="shipping"
|
2023-08-09 17:24:51 +00:00
|
|
|
onChange={ onChangeAddress }
|
2022-02-22 17:45:01 +00:00
|
|
|
values={ shippingAddress }
|
|
|
|
fields={
|
|
|
|
Object.keys(
|
|
|
|
defaultAddressFields
|
|
|
|
) as ( keyof AddressFields )[]
|
|
|
|
}
|
2021-07-22 11:03:00 +00:00
|
|
|
fieldConfig={ addressFieldsConfig }
|
|
|
|
/>
|
|
|
|
{ showPhoneField && (
|
|
|
|
<PhoneNumber
|
|
|
|
id="shipping-phone"
|
2023-01-24 14:52:59 +00:00
|
|
|
errorId={ 'shipping_phone' }
|
2021-07-22 11:03:00 +00:00
|
|
|
isRequired={ requirePhoneField }
|
2022-02-22 17:45:01 +00:00
|
|
|
value={ shippingAddress.phone }
|
2021-07-22 11:03:00 +00:00
|
|
|
onChange={ ( value ) => {
|
|
|
|
setShippingPhone( value );
|
|
|
|
dispatchCheckoutEvent( 'set-phone-number', {
|
|
|
|
step: 'shipping',
|
|
|
|
} );
|
|
|
|
} }
|
|
|
|
/>
|
|
|
|
) }
|
|
|
|
</AddressFormWrapperComponent>
|
|
|
|
<CheckboxControl
|
|
|
|
className="wc-block-checkout__use-address-for-billing"
|
|
|
|
label={ __(
|
|
|
|
'Use same address for billing',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
) }
|
2022-02-22 17:45:01 +00:00
|
|
|
checked={ useShippingAsBilling }
|
|
|
|
onChange={ ( checked: boolean ) => {
|
|
|
|
setUseShippingAsBilling( checked );
|
|
|
|
if ( checked ) {
|
2022-06-10 16:59:25 +00:00
|
|
|
setBillingAddress( shippingAddress as BillingAddress );
|
2022-02-22 17:45:01 +00:00
|
|
|
}
|
|
|
|
} }
|
2021-07-22 11:03:00 +00:00
|
|
|
/>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Block;
|