2021-09-21 12:20:42 +00:00
/ * *
* External dependencies
* /
2021-10-25 15:31:22 +00:00
import classnames from 'classnames' ;
2023-04-20 09:30:29 +00:00
import { useState , useEffect , useMemo } from '@wordpress/element' ;
2021-10-19 14:29:12 +00:00
import Button from '@woocommerce/base-components/button' ;
import { CHECKOUT_URL } from '@woocommerce/block-settings' ;
import { usePositionRelativeToViewport } from '@woocommerce/base-hooks' ;
2021-09-21 12:20:42 +00:00
import { getSetting } from '@woocommerce/settings' ;
2022-06-10 16:33:15 +00:00
import { useSelect } from '@wordpress/data' ;
2023-03-13 07:34:12 +00:00
import { CART_STORE_KEY , CHECKOUT_STORE_KEY } from '@woocommerce/block-data' ;
import { applyCheckoutFilter } from '@woocommerce/blocks-checkout' ;
2023-06-19 15:44:37 +00:00
import { isErrorResponse } from '@woocommerce/base-context' ;
import { useCartEventsContext } from '@woocommerce/base-context/providers' ;
2021-09-21 12:20:42 +00:00
/ * *
* Internal dependencies
* /
2022-12-13 14:54:27 +00:00
import { defaultButtonLabel } from './constants' ;
2021-09-21 12:20:42 +00:00
2021-10-19 14:29:12 +00:00
/ * *
* Checkout button rendered in the full cart page .
* /
2021-09-21 12:20:42 +00:00
const Block = ( {
checkoutPageId ,
2021-10-25 15:31:22 +00:00
className ,
2022-12-13 14:54:27 +00:00
buttonLabel ,
2021-09-21 12:20:42 +00:00
} : {
checkoutPageId : number ;
2021-10-25 15:31:22 +00:00
className : string ;
2022-12-13 14:54:27 +00:00
buttonLabel : string ;
2021-09-21 12:20:42 +00:00
} ) : JSX . Element = > {
2023-03-13 07:34:12 +00:00
const link = getSetting < string > ( 'page-' + checkoutPageId , false ) ;
2022-06-10 16:33:15 +00:00
const isCalculating = useSelect ( ( select ) = >
select ( CHECKOUT_STORE_KEY ) . isCalculating ( )
) ;
2023-03-13 07:34:12 +00:00
2022-06-23 09:15:25 +00:00
const [ positionReferenceElement , positionRelativeToViewport ] =
usePositionRelativeToViewport ( ) ;
2021-10-19 14:29:12 +00:00
const [ showSpinner , setShowSpinner ] = useState ( false ) ;
useEffect ( ( ) = > {
// Add a listener to remove the spinner on the checkout button, so the saved page snapshot does not
// contain the spinner class. See https://archive.is/lOEW0 for why this is needed for Safari.
if (
typeof global . addEventListener !== 'function' ||
typeof global . removeEventListener !== 'function'
) {
return ;
}
const hideSpinner = ( ) = > {
setShowSpinner ( false ) ;
} ;
global . addEventListener ( 'pageshow' , hideSpinner ) ;
return ( ) = > {
global . removeEventListener ( 'pageshow' , hideSpinner ) ;
} ;
} , [ ] ) ;
2023-03-13 07:34:12 +00:00
const cart = useSelect ( ( select ) = > {
return select ( CART_STORE_KEY ) . getCartData ( ) ;
} ) ;
const label = applyCheckoutFilter < string > ( {
filterName : 'proceedToCheckoutButtonLabel' ,
defaultValue : buttonLabel || defaultButtonLabel ,
arg : { cart } ,
} ) ;
const filteredLink = applyCheckoutFilter < string > ( {
filterName : 'proceedToCheckoutButtonLink' ,
defaultValue : link || CHECKOUT_URL ,
arg : { cart } ,
} ) ;
2021-10-19 14:29:12 +00:00
2023-06-19 15:44:37 +00:00
const { dispatchOnProceedToCheckout } = useCartEventsContext ( ) ;
2021-10-19 14:29:12 +00:00
const submitContainerContents = (
< Button
className = "wc-block-cart__submit-button"
2023-03-13 07:34:12 +00:00
href = { filteredLink }
2021-10-19 14:29:12 +00:00
disabled = { isCalculating }
2023-06-19 15:44:37 +00:00
onClick = { ( e ) = > {
dispatchOnProceedToCheckout ( ) . then ( ( observerResponses ) = > {
if ( observerResponses . some ( isErrorResponse ) ) {
e . preventDefault ( ) ;
return ;
}
setShowSpinner ( true ) ;
} ) ;
} }
2021-10-19 14:29:12 +00:00
showSpinner = { showSpinner }
>
2023-03-13 07:34:12 +00:00
{ label }
2021-10-19 14:29:12 +00:00
< / Button >
) ;
2023-04-19 17:15:10 +00:00
// Get the body background color to use as the sticky container background color.
2023-04-20 09:30:29 +00:00
const backgroundColor = useMemo (
( ) = > getComputedStyle ( document . body ) . backgroundColor ,
[ ]
) ;
2023-04-19 17:15:10 +00:00
2021-09-21 12:20:42 +00:00
return (
2021-10-25 15:31:22 +00:00
< div className = { classnames ( 'wc-block-cart__submit' , className ) } >
2021-10-19 14:29:12 +00:00
{ positionReferenceElement }
{ /* The non-sticky container must always be visible because it gives height to its parent, which is required to calculate when it becomes visible in the viewport. */ }
< div className = "wc-block-cart__submit-container" >
{ submitContainerContents }
< / div >
{ /* If the positionReferenceElement is below the viewport, display the sticky container. */ }
{ positionRelativeToViewport === 'below' && (
2023-04-19 17:15:10 +00:00
< div
className = "wc-block-cart__submit-container wc-block-cart__submit-container--sticky"
style = { { backgroundColor } }
>
2021-10-19 14:29:12 +00:00
{ submitContainerContents }
< / div >
) }
< / div >
2021-09-21 12:20:42 +00:00
) ;
} ;
export default Block ;