Add totalValue filter (#45170)

* Add totalValue filter

* Add changefile(s) from automation for the following project(s): woocommerce-blocks

* Remove nowrap to prevent text overflow

* Start docs for ‘totalValue’ filter

* Fix *.md lint issues

* Ignore .md lint errors for now

* Update code example and add screenshots

* Fix failing JS unit tests

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Niels Lange 2024-03-13 00:42:24 +07:00 committed by GitHub
parent 55ec9eca2d
commit 6b07ca44f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 141 additions and 53 deletions

View File

@ -13,7 +13,10 @@ import {
useStoreCart,
} from '@woocommerce/base-context/hooks';
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
import { applyCheckoutFilter, mustContain } from '@woocommerce/blocks-checkout';
import {
applyCheckoutFilter,
productPriceValidation,
} from '@woocommerce/blocks-checkout';
import Dinero from 'dinero.js';
import { forwardRef, useMemo } from '@wordpress/element';
import type { CartItem } from '@woocommerce/types';
@ -43,9 +46,6 @@ const getAmountFromRawPrice = (
return priceObject.convertPrecision( currency.minorUnit ).getAmount();
};
const productPriceValidation = ( value: string ) =>
mustContain( value, '<price/>' );
interface CartLineItemRowProps {
lineItem: CartItem | Record< string, never >;
onRemove?: () => void;

View File

@ -10,7 +10,10 @@ import {
getCurrencyFromPriceResponse,
formatPrice,
} from '@woocommerce/price-format';
import { applyCheckoutFilter, mustContain } from '@woocommerce/blocks-checkout';
import {
applyCheckoutFilter,
productPriceValidation,
} from '@woocommerce/blocks-checkout';
import Dinero from 'dinero.js';
import { getSetting } from '@woocommerce/settings';
import { useMemo } from '@wordpress/element';
@ -25,9 +28,6 @@ import ProductImage from '../product-image';
import ProductLowStockBadge from '../product-low-stock-badge';
import ProductMetadata from '../product-metadata';
const productPriceValidation = ( value: string ): true | never =>
mustContain( value, '<price/>' );
interface OrderSummaryProps {
cartItem: CartItem;
}

View File

@ -8,7 +8,10 @@ import {
FormattedMonetaryAmount,
TotalsItem,
} from '@woocommerce/blocks-components';
import { applyCheckoutFilter } from '@woocommerce/blocks-checkout';
import {
applyCheckoutFilter,
productPriceValidation,
} from '@woocommerce/blocks-checkout';
import { useStoreCart } from '@woocommerce/base-context/hooks';
import { getSetting } from '@woocommerce/settings';
import {
@ -64,6 +67,7 @@ const TotalsFooterItem = ( {
// We need to pluck out receiveCart.
// eslint-disable-next-line no-unused-vars
const { receiveCart, ...cart } = useStoreCart();
const label = applyCheckoutFilter( {
filterName: 'totalLabel',
defaultValue: __( 'Total', 'woocommerce' ),
@ -71,7 +75,28 @@ const TotalsFooterItem = ( {
arg: { cart },
} );
const totalValue = applyCheckoutFilter( {
filterName: 'totalValue',
defaultValue: '<price/>',
extensions: cart.extensions,
arg: { cart },
validation: productPriceValidation,
} );
const priceComponent = (
<FormattedMonetaryAmount
className="wc-block-components-totals-item__value"
currency={ currency }
value={ parseInt( totalPrice, 10 ) }
/>
);
const value = createInterpolateElement( totalValue, {
price: priceComponent,
} );
const parsedTaxValue = parseInt( totalTax, 10 );
const description =
taxLines && taxLines.length > 0
? sprintf(
@ -96,7 +121,7 @@ const TotalsFooterItem = ( {
) }
currency={ currency }
label={ label }
value={ parseInt( totalPrice, 10 ) }
value={ value }
description={
SHOW_TAXES &&
parsedTaxValue !== 0 && (

View File

@ -2,14 +2,14 @@
## Table of Contents <!-- omit in toc -->
- [Contributors](#contributors)
- [Internal developers](#internal-developers)
- [Third-party developers](#third-party-developers)
- [Designers](#designers)
- [Developer Resources](#developer-resources)
- [Tools](#tools)
- [Articles](#articles)
- [Tutorials](#tutorials)
- [Contributors](#contributors)
- [Internal developers](#internal-developers)
- [Third-party developers](#third-party-developers)
- [Designers](#designers)
- [Developer Resources](#developer-resources)
- [Tools](#tools)
- [Articles](#articles)
- [Tutorials](#tutorials)
The WooCommerce Blocks Handbook provides documentation for designers and developers on how to extend or contribute to blocks, and how internal developers should handle new releases.
@ -152,4 +152,3 @@ The following tutorials from [developer.woo.com](https://developer.woo.com/categ
🐞 Found a mistake, or have a suggestion? [Leave feedback about this document here.](https://github.com/woocommerce/woocommerce-blocks/issues/new?assignees=&labels=type%3A+documentation&template=--doc-feedback.md&title=Feedback%20on%20./docs/README.md)
<!-- /FEEDBACK -->

View File

@ -2,25 +2,25 @@
## Table of Contents <!-- omit in toc -->
- [General Concepts](#general-concepts)
- [Tracking flow through status](#tracking-flow-through-status)
- [Checkout Data Store Status](#checkout-data-store-status)
- [Special States](#special-states)
- [`ShippingProvider` Exposed Statuses](#shippingprovider-exposed-statuses)
- [Payment Method Data Store Status](#payment-method-data-store-status)
- [Emitting Events](#emitting-events)
- [`onCheckoutValidation`](#oncheckoutvalidation)
- [~~`onPaymentProcessing`~~](#onpaymentprocessing)
- [`onPaymentSetup`](#onpaymentsetup)
- [Success](#success)
- [Fail](#fail)
- [Error](#error)
- [`onCheckoutSuccess`](#oncheckoutsuccess)
- [`onCheckoutFail`](#oncheckoutfail)
- [`onShippingRateSuccess`](#onshippingratesuccess)
- [`onShippingRateFail`](#onshippingratefail)
- [`onShippingRateSelectSuccess`](#onshippingrateselectsuccess)
- [`onShippingRateSelectFail`](#onshippingrateselectfail)
- [General Concepts](#general-concepts)
- [Tracking flow through status](#tracking-flow-through-status)
- [Checkout Data Store Status](#checkout-data-store-status)
- [Special States](#special-states)
- [`ShippingProvider` Exposed Statuses](#shippingprovider-exposed-statuses)
- [Payment Method Data Store Status](#payment-method-data-store-status)
- [Emitting Events](#emitting-events)
- [`onCheckoutValidation`](#oncheckoutvalidation)
- [~~`onPaymentProcessing`~~](#onpaymentprocessing)
- [`onPaymentSetup`](#onpaymentsetup)
- [Success](#success)
- [Fail](#fail)
- [Error](#error)
- [`onCheckoutSuccess`](#oncheckoutsuccess)
- [`onCheckoutFail`](#oncheckoutfail)
- [`onShippingRateSuccess`](#onshippingratesuccess)
- [`onShippingRateFail`](#onshippingratefail)
- [`onShippingRateSelectSuccess`](#onshippingrateselectsuccess)
- [`onShippingRateSelectFail`](#onshippingrateselectfail)
This document gives an overview of the flow for the checkout in the WooCommerce checkout block, and some general architectural overviews.

View File

@ -45,15 +45,16 @@ The following screenshot shows which parts the individual filters affect:
The following [Totals Footer Item filter](./available-filters/totals-footer-item.md) is available:
- [totalLabel](./available-filters/totals-footer-item.md#totallabel)
- [`totalLabel`](./available-filters/totals-footer-item.md#totallabel)
- [`totalValue`](./available-filters/totals-footer-item.md#totalvalue)
## Checkout and place order button filters
The following [Checkout and place order button filters](./available-filters/checkout-and-place-order-button.md) are available:
- [proceedToCheckoutButtonLabel](./available-filters/checkout-and-place-order-button.md#proceedtocheckoutbuttonlabel)
- [proceedToCheckoutButtonLink](./available-filters/checkout-and-place-order-button.md#proceedtocheckoutbuttonlink)
- [placeOrderButtonLabel](./available-filters/checkout-and-place-order-button.md#placeorderbuttonlabel)
- [`proceedToCheckoutButtonLabel`](./available-filters/checkout-and-place-order-button.md#proceedtocheckoutbuttonlabel)
- [`proceedToCheckoutButtonLink`](./available-filters/checkout-and-place-order-button.md#proceedtocheckoutbuttonlink)
- [`placeOrderButtonLabel`](./available-filters/checkout-and-place-order-button.md#placeorderbuttonlabel)
## Coupon filters

View File

@ -1,19 +1,22 @@
<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD033 -->
# Totals Footer Item
The following Totals Footer Item filter is available:
The following Totals Footer Item filter are available:
- [totalLabel](#totallabel)
- [`totalLabel`](#totallabel)
- [`totalValue`](#totalvalue)
## `totalLabel`
The following objects are used in the filter:
The following object is used in the filter:
- [Cart object](#cart-object)
- [Cart Item object](#cart-item-object)
### Description <!-- omit in toc -->
The `totalLabel` filter allows you to change the label of the total item in the footer of the Cart and Checkout blocks.
The `totalLabel` filter allows to change the label of the total item in the footer of the Cart and Checkout blocks.
### Parameters <!-- omit in toc -->
@ -57,6 +60,59 @@ registerCheckoutFilters( 'example-extension', {
</tr>
</table>
## `totalValue`
The following object is used in the filter:
- [Cart object](#cart-object)
### Description <!-- omit in toc -->
The `totalValue` filter allows to format the total price in the footer of the Cart and Checkout blocks.
### Parameters <!-- omit in toc -->
- _defaultValue_ `string` (default: `Total`) - The total label.
- _extensions_ `object` (default: `{}`) - The extensions object.
- _args_ `object` - The arguments object with the following keys:
- _cart_ `object` - The cart object from `wc/store/cart`, see [Cart object](#cart-object).
- _validation_ `boolean` - Checks if the return value contains the substring `<price/>`.
### Returns <!-- omit in toc -->
- `string` - The modified format of the total price, which must contain the substring `<price/>`, or the original price format.
### Code example <!-- omit in toc -->
```ts
const { registerCheckoutFilters } = window.wc.blocksCheckout;
const modifyTotalsPrice = ( defaultValue, extensions, args, validation ) => {
return 'Pay <price/> now';
};
registerCheckoutFilters( 'my-extension', {
totalValue: modifyTotalsPrice,
} );
```
> 💡 Filters can be also combined. See [Combined filters](../available-filters.md#combined-filters) for an example.
### Screenshots <!-- omit in toc -->
<table>
<tr>
<td valign="top">Before:
<br><br>
<img width="361" alt="Before applying the Total Value filter" src="https://github.com/woocommerce/woocommerce/assets/3323310/4b788bdd-6fbd-406c-a9ad-4fb13f901c23">
</td>
<td valign="top">After:
<br><br>
<img width="355" alt="After applying the Total Value filter" src="https://github.com/woocommerce/woocommerce/assets/3323310/1b1b5f72-7f2f-4ee5-b2a4-1d8eb2208deb">
</td>
</tr>
</table>
## Cart object
The Cart object of the filters above has the following keys:

View File

@ -1,3 +1,4 @@
export { default as mustContain } from './must-contain';
export { default as getValidityMessageForInput } from './get-validity-message-for-input';
export { default as isPostcode } from './is-postcode';
export { productPriceValidation } from './validate-filter';

View File

@ -0,0 +1,7 @@
/**
* Internal dependencies
*/
import mustContain from './must-contain';
export const productPriceValidation = ( value: string ) =>
mustContain( value, '<price/>' );

View File

@ -26,11 +26,7 @@ const TotalsItemValue = ( {
currency,
}: Partial< TotalsItemProps > ): ReactElement | null => {
if ( isValidElement( value ) ) {
return (
<div className="wc-block-components-totals-item__value">
{ value }
</div>
);
return <>{ value }</>;
}
return Number.isFinite( value ) ? (

View File

@ -11,7 +11,6 @@
.wc-block-components-totals-item__value {
font-weight: bold;
white-space: nowrap;
}
.wc-block-components-totals-item__description {

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add totalValue filter.