2020-05-06 10:21:30 +00:00
/ * *
* External dependencies
* /
2021-04-08 12:31:12 +00:00
import { defaultAddressFields } from '@woocommerce/settings' ;
2020-11-20 15:13:35 +00:00
import { useState , useEffect , useCallback , useRef } from '@wordpress/element' ;
2021-04-08 12:31:12 +00:00
/ * *
* Internal dependencies
* /
2020-05-06 10:21:30 +00:00
import {
useShippingDataContext ,
2020-11-20 15:13:35 +00:00
useCustomerDataContext ,
2020-05-06 10:21:30 +00:00
useCheckoutContext ,
2021-04-08 12:31:12 +00:00
} from '../providers/cart-checkout' ;
2020-05-06 10:21:30 +00:00
/ * *
* Compare two addresses and see if they are the same .
*
* @ param { Object } address1 First address .
* @ param { Object } address2 Second address .
* /
const isSameAddress = ( address1 , address2 ) => {
return Object . keys ( defaultAddressFields ) . every (
( field ) => address1 [ field ] === address2 [ field ]
) ;
} ;
/ * *
2020-11-20 15:13:35 +00:00
* Custom hook for exposing address related functionality for the checkout address form .
2020-05-06 10:21:30 +00:00
* /
export const useCheckoutAddress = ( ) => {
const { customerId } = useCheckoutContext ( ) ;
2020-11-20 15:13:35 +00:00
const { needsShipping } = useShippingDataContext ( ) ;
2020-05-06 10:21:30 +00:00
const {
2020-11-20 15:13:35 +00:00
billingData ,
setBillingData ,
2020-05-06 10:21:30 +00:00
shippingAddress ,
setShippingAddress ,
2020-11-20 15:13:35 +00:00
} = useCustomerDataContext ( ) ;
2020-05-06 10:21:30 +00:00
// This tracks the state of the "shipping as billing" address checkbox. It's
// initial value is true (if shipping is needed), however, if the user is
// logged in and they have a different billing address, we can toggle this off.
const [ shippingAsBilling , setShippingAsBilling ] = useState (
( ) =>
needsShipping &&
( ! customerId || isSameAddress ( shippingAddress , billingData ) )
) ;
2020-11-20 15:13:35 +00:00
const currentShippingAsBilling = useRef ( shippingAsBilling ) ;
const previousBillingData = useRef ( billingData ) ;
2020-05-06 10:21:30 +00:00
/ * *
2020-11-20 15:13:35 +00:00
* Sets shipping address data , and also billing if using the same address .
2020-05-06 10:21:30 +00:00
* /
2020-11-20 15:13:35 +00:00
const setShippingFields = useCallback (
( value ) => {
setShippingAddress ( value ) ;
if ( shippingAsBilling ) {
setBillingData ( value ) ;
}
} ,
[ shippingAsBilling , setShippingAddress , setBillingData ]
2020-05-14 00:05:09 +00:00
) ;
2020-05-06 10:21:30 +00:00
2020-12-23 15:10:13 +00:00
/ * *
* Sets billing address data , and also shipping if shipping is disabled .
* /
const setBillingFields = useCallback (
( value ) => {
setBillingData ( value ) ;
if ( ! needsShipping ) {
setShippingAddress ( value ) ;
}
} ,
[ needsShipping , setShippingAddress , setBillingData ]
) ;
2020-11-20 15:13:35 +00:00
// When the "Use same address" checkbox is toggled we need to update the current billing address to reflect this;
// that is either setting the billing address to the shipping address, or restoring the billing address to it's
// previous state.
useEffect ( ( ) => {
if ( currentShippingAsBilling . current !== shippingAsBilling ) {
if ( shippingAsBilling ) {
previousBillingData . current = billingData ;
setBillingData ( shippingAddress ) ;
} else {
2021-05-05 11:59:30 +00:00
const {
// We need to pluck out email and phone from previous billing data because they can be empty, causing the current email and phone to get emptied. See issue #4155
/* eslint-disable no-unused-vars */
email ,
phone ,
/* eslint-enable no-unused-vars */
... billingAddress
} = previousBillingData . current ;
2020-11-20 15:13:35 +00:00
setBillingData ( {
2021-05-05 11:59:30 +00:00
... billingAddress ,
2020-11-20 15:13:35 +00:00
} ) ;
}
currentShippingAsBilling . current = shippingAsBilling ;
}
} , [ shippingAsBilling , setBillingData , shippingAddress , billingData ] ) ;
2020-12-23 15:10:13 +00:00
const setEmail = ( value ) =>
void setBillingData ( {
email : value ,
} ) ;
const setPhone = ( value ) =>
void setBillingData ( {
phone : value ,
} ) ;
2020-05-06 10:21:30 +00:00
2020-11-20 15:13:35 +00:00
// Note that currentShippingAsBilling is returned rather than the current state of shippingAsBilling--this is so that
// the billing fields are not rendered before sync (billing field values are debounced and would be outdated)
2020-05-06 10:21:30 +00:00
return {
defaultAddressFields ,
2020-05-14 00:05:09 +00:00
shippingFields : shippingAddress ,
2020-11-20 15:13:35 +00:00
setShippingFields ,
billingFields : billingData ,
2020-12-23 15:10:13 +00:00
setBillingFields ,
2020-05-06 10:21:30 +00:00
setEmail ,
setPhone ,
shippingAsBilling ,
setShippingAsBilling ,
2020-11-20 15:13:35 +00:00
showBillingFields :
! needsShipping || ! currentShippingAsBilling . current ,
2020-05-06 10:21:30 +00:00
} ;
} ;