Mini Cart block: add footer (subtotal, cart & checkout buttons and payment method icons) (https://github.com/woocommerce/woocommerce-blocks/pull/4982)

Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
This commit is contained in:
Tung Du 2021-10-28 22:48:39 +07:00 committed by GitHub
parent edaf0f094d
commit e60405689d
6 changed files with 182 additions and 8 deletions

View File

@ -42,7 +42,7 @@ $drawer-width-mobile: 100vw;
right: 0; right: 0;
top: 0; top: 0;
transition: opacity $drawer-animation-duration; transition: opacity $drawer-animation-duration;
z-index: 999; z-index: 9999;
opacity: 1; opacity: 1;
} }

View File

@ -0,0 +1,26 @@
/**
* External dependencies
*/
import type {
PaymentMethods,
PaymentMethodIcons as PaymentMethodIconsType,
} from '@woocommerce/type-defs/payments';
/**
* Get the provider icons from payment methods data.
*
* @todo Refactor the Cart blocks to use getIconsFromPaymentMethods utility instead of the local copy.
*
* @param {PaymentMethods} paymentMethods Payment Method data
* @return {PaymentMethodIconsType} Payment Method icons data.
*/
export const getIconsFromPaymentMethods = (
paymentMethods: PaymentMethods
): PaymentMethodIconsType => {
return Object.values( paymentMethods ).reduce( ( acc, paymentMethod ) => {
if ( paymentMethod.icons !== null ) {
acc = acc.concat( paymentMethod.icons );
}
return acc;
}, [] as PaymentMethodIconsType );
};

View File

@ -7,3 +7,4 @@ export * from './get-valid-block-attributes';
export * from './product-data'; export * from './product-data';
export * from './derive-selected-shipping-rates'; export * from './derive-selected-shipping-rates';
export * from './from-entries-polyfill'; export * from './from-entries-polyfill';
export * from './get-icons-from-payment-methods';

View File

@ -4,14 +4,25 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { __, _n, sprintf } from '@wordpress/i18n'; import { __, _n, sprintf } from '@wordpress/i18n';
import { useState, useEffect, useRef } from '@wordpress/element'; import { useState, useEffect, useRef } from '@wordpress/element';
import { translateJQueryEventToNative } from '@woocommerce/base-utils'; import {
import { useStoreCart } from '@woocommerce/base-context/hooks'; translateJQueryEventToNative,
getIconsFromPaymentMethods,
} from '@woocommerce/base-utils';
import {
useStoreCart,
usePaymentMethods,
} from '@woocommerce/base-context/hooks';
import Drawer from '@woocommerce/base-components/drawer'; import Drawer from '@woocommerce/base-components/drawer';
import { import {
formatPrice, formatPrice,
getCurrencyFromPriceResponse, getCurrencyFromPriceResponse,
} from '@woocommerce/price-format'; } from '@woocommerce/price-format';
import { getSetting } from '@woocommerce/settings'; import { getSetting } from '@woocommerce/settings';
import { TotalsItem } from '@woocommerce/blocks-checkout';
import PaymentMethodIcons from '@woocommerce/base-components/cart-checkout/payment-method-icons';
import { CART_URL, CHECKOUT_URL } from '@woocommerce/block-settings';
import Button from '@woocommerce/base-components/button';
import { PaymentMethodDataProvider } from '@woocommerce/base-context';
/** /**
* Internal dependencies * Internal dependencies
@ -23,6 +34,15 @@ interface MiniCartBlockProps {
isInitiallyOpen?: boolean; isInitiallyOpen?: boolean;
} }
const PaymentMethodIconsElement = (): JSX.Element => {
const { paymentMethods } = usePaymentMethods();
return (
<PaymentMethodIcons
icons={ getIconsFromPaymentMethods( paymentMethods ) }
/>
);
};
const MiniCartBlock = ( { const MiniCartBlock = ( {
isInitiallyOpen = false, isInitiallyOpen = false,
}: MiniCartBlockProps ): JSX.Element => { }: MiniCartBlockProps ): JSX.Element => {
@ -80,7 +100,7 @@ const MiniCartBlock = ( {
const subTotal = getSetting( 'displayCartPricesIncludingTax', false ) const subTotal = getSetting( 'displayCartPricesIncludingTax', false )
? parseInt( cartTotals.total_items, 10 ) + ? parseInt( cartTotals.total_items, 10 ) +
parseInt( cartTotals.total_items_tax, 10 ) parseInt( cartTotals.total_items_tax, 10 )
: cartTotals.total_items; : parseInt( cartTotals.total_items, 10 );
const ariaLabel = sprintf( const ariaLabel = sprintf(
/* translators: %1$d is the number of products in the cart. %2$s is the cart total */ /* translators: %1$d is the number of products in the cart. %2$s is the cart total */
@ -104,10 +124,52 @@ const MiniCartBlock = ( {
{ __( 'Cart is empty', 'woo-gutenberg-products-block' ) } { __( 'Cart is empty', 'woo-gutenberg-products-block' ) }
</div> </div>
) : ( ) : (
<>
<div className="wc-block-mini-cart__items">
<CartLineItemsTable <CartLineItemsTable
lineItems={ cartItems } lineItems={ cartItems }
isLoading={ cartIsLoading } isLoading={ cartIsLoading }
/> />
</div>
<div className="wc-block-mini-cart__footer">
<TotalsItem
className="wc-block-mini-cart__footer-subtotal"
currency={ getCurrencyFromPriceResponse( cartTotals ) }
label={ __(
'Subtotal',
'woo-gutenberg-products-block'
) }
value={ subTotal }
description={ __(
'Shipping, taxes, and discounts calculated at checkout.',
'woo-gutenberg-products-block'
) }
/>
<div className="wc-block-mini-cart__footer-actions">
<Button
className="wc-block-mini-cart__footer-cart"
href={ CART_URL }
>
{ __(
'View my cart',
'woo-gutenberg-products-block'
) }
</Button>
<Button
className="wc-block-mini-cart__footer-checkout"
href={ CHECKOUT_URL }
>
{ __(
'Go to checkout',
'woo-gutenberg-products-block'
) }
</Button>
</div>
<PaymentMethodDataProvider>
<PaymentMethodIconsElement />
</PaymentMethodDataProvider>
</div>
</>
); );
return ( return (

View File

@ -5,4 +5,77 @@
// Reset font size so it doesn't depend on drawer's ancestors. // Reset font size so it doesn't depend on drawer's ancestors.
.wc-block-mini-cart__drawer { .wc-block-mini-cart__drawer {
font-size: 1rem; font-size: 1rem;
.components-modal__content {
display: flex;
flex-direction: column;
height: 100%;
}
.components-modal__header {
margin: $gap 0;
}
.wc-block-mini-cart__items {
flex-grow: 1;
margin-right: -$gap;
overflow-y: auto;
padding-right: $gap;
.wc-block-cart-items__row:last-child::after {
content: none;
}
}
}
.wc-block-mini-cart__footer {
border-top: 1px solid $gray-300;
margin-bottom: -$gap-largest;
margin-left: -$gap;
margin-right: -$gap;
padding: $gap-large;
}
.wc-block-components-totals-item.wc-block-mini-cart__footer-subtotal {
font-weight: 600;
margin-bottom: $gap;
.wc-block-components-totals-item__description {
display: none;
font-size: 0.75em;
font-weight: 400;
@media only screen and (min-width: 480px) {
display: unset;
}
}
}
.wc-block-mini-cart__footer-actions {
display: flex;
gap: $gap;
.wc-block-mini-cart__footer-cart.wc-block-components-button {
background-color: transparent;
border: 1px solid $gray-900;
color: $gray-900;
display: none;
flex-grow: 1;
font-weight: 600;
@media only screen and (min-width: 480px) {
display: inline-flex;
}
}
.wc-block-mini-cart__footer-checkout {
border: 1px solid $gray-900;
flex-grow: 1;
font-weight: 600;
}
}
.wc-block-mini-cart__footer .wc-block-components-payment-method-icons {
margin-top: $gap;
} }

View File

@ -5,6 +5,7 @@ use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Assets; use Automattic\WooCommerce\Blocks\Assets;
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry; use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\CartController; use Automattic\WooCommerce\Blocks\StoreApi\Utilities\CartController;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
/** /**
* Mini Cart class. * Mini Cart class.
@ -96,6 +97,14 @@ class MiniCart extends AbstractBlock {
} }
} }
$payment_method_registry = Package::container()->get( PaymentMethodRegistry::class );
$payment_methods = $payment_method_registry->get_all_active_payment_method_script_dependencies();
foreach ( $payment_methods as $payment_method ) {
$payment_method_script = $this->get_script_from_handle( $payment_method );
$this->append_script_and_deps_src( $payment_method_script );
}
$this->scripts_to_lazy_load['wc-block-mini-cart-component-frontend'] = array( $this->scripts_to_lazy_load['wc-block-mini-cart-component-frontend'] = array(
'src' => $script_data['src'], 'src' => $script_data['src'],
'version' => $script_data['version'], 'version' => $script_data['version'],
@ -165,6 +174,9 @@ class MiniCart extends AbstractBlock {
} }
} }
} }
if ( ! $script->src ) {
return;
}
$this->scripts_to_lazy_load[ $script->handle ] = array( $this->scripts_to_lazy_load[ $script->handle ] = array(
'src' => $script->src, 'src' => $script->src,
'version' => $script->ver, 'version' => $script->ver,