diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/cart-line-items-table/cart-line-item-row.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/cart-line-items-table/cart-line-item-row.tsx index 9a3c0a0967d2..f294d9313185 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/cart-line-items-table/cart-line-item-row.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/cart-line-items-table/cart-line-item-row.tsx @@ -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, '' ); - interface CartLineItemRowProps { lineItem: CartItem | Record< string, never >; onRemove?: () => void; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.tsx index 405087dc9750..950276247abf 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.tsx @@ -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, '' ); - interface OrderSummaryProps { cartItem: CartItem; } diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/footer-item/index.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/footer-item/index.tsx index 9b1ac9af26b9..b9948793df5f 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/footer-item/index.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/footer-item/index.tsx @@ -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: '', + extensions: cart.extensions, + arg: { cart }, + validation: productPriceValidation, + } ); + + const priceComponent = ( + + ); + + 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 && ( diff --git a/plugins/woocommerce-blocks/docs/README.md b/plugins/woocommerce-blocks/docs/README.md index f5da0f090c02..0b39430b03fc 100644 --- a/plugins/woocommerce-blocks/docs/README.md +++ b/plugins/woocommerce-blocks/docs/README.md @@ -2,14 +2,14 @@ ## Table of Contents -- [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) - diff --git a/plugins/woocommerce-blocks/docs/internal-developers/block-client-apis/checkout/checkout-flow-and-events.md b/plugins/woocommerce-blocks/docs/internal-developers/block-client-apis/checkout/checkout-flow-and-events.md index 316ba480a61e..757a64425d26 100644 --- a/plugins/woocommerce-blocks/docs/internal-developers/block-client-apis/checkout/checkout-flow-and-events.md +++ b/plugins/woocommerce-blocks/docs/internal-developers/block-client-apis/checkout/checkout-flow-and-events.md @@ -2,25 +2,25 @@ ## Table of Contents -- [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. diff --git a/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters.md b/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters.md index adee065f67aa..6f3d4c3d4c9a 100644 --- a/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters.md +++ b/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters.md @@ -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 diff --git a/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters/totals-footer-item.md b/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters/totals-footer-item.md index e8859f8a949c..3f33233aa359 100644 --- a/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters/totals-footer-item.md +++ b/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/available-filters/totals-footer-item.md @@ -1,19 +1,22 @@ + + + # 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 -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 @@ -57,6 +60,59 @@ registerCheckoutFilters( 'example-extension', { +## `totalValue` + +The following object is used in the filter: + +- [Cart object](#cart-object) + +### Description + +The `totalValue` filter allows to format the total price in the footer of the Cart and Checkout blocks. + +### Parameters + +- _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 ``. + +### Returns + +- `string` - The modified format of the total price, which must contain the substring ``, or the original price format. + +### Code example + +```ts +const { registerCheckoutFilters } = window.wc.blocksCheckout; + +const modifyTotalsPrice = ( defaultValue, extensions, args, validation ) => { + return 'Pay now'; +}; + +registerCheckoutFilters( 'my-extension', { + totalValue: modifyTotalsPrice, +} ); +``` + +> 💡 Filters can be also combined. See [Combined filters](../available-filters.md#combined-filters) for an example. + +### Screenshots + + + + + + +
Before: +

+Before applying the Total Value filter +
After: +

+After applying the Total Value filter +
+ ## Cart object The Cart object of the filters above has the following keys: diff --git a/plugins/woocommerce-blocks/packages/checkout/utils/validation/index.ts b/plugins/woocommerce-blocks/packages/checkout/utils/validation/index.ts index 8dcafa3d8696..190d7472f7ef 100644 --- a/plugins/woocommerce-blocks/packages/checkout/utils/validation/index.ts +++ b/plugins/woocommerce-blocks/packages/checkout/utils/validation/index.ts @@ -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'; diff --git a/plugins/woocommerce-blocks/packages/checkout/utils/validation/validate-filter.ts b/plugins/woocommerce-blocks/packages/checkout/utils/validation/validate-filter.ts new file mode 100644 index 000000000000..fddc286d2a9e --- /dev/null +++ b/plugins/woocommerce-blocks/packages/checkout/utils/validation/validate-filter.ts @@ -0,0 +1,7 @@ +/** + * Internal dependencies + */ +import mustContain from './must-contain'; + +export const productPriceValidation = ( value: string ) => + mustContain( value, '' ); diff --git a/plugins/woocommerce-blocks/packages/components/totals/item/index.tsx b/plugins/woocommerce-blocks/packages/components/totals/item/index.tsx index 529835dcd597..17bd6489998b 100644 --- a/plugins/woocommerce-blocks/packages/components/totals/item/index.tsx +++ b/plugins/woocommerce-blocks/packages/components/totals/item/index.tsx @@ -26,11 +26,7 @@ const TotalsItemValue = ( { currency, }: Partial< TotalsItemProps > ): ReactElement | null => { if ( isValidElement( value ) ) { - return ( -
- { value } -
- ); + return <>{ value }; } return Number.isFinite( value ) ? ( diff --git a/plugins/woocommerce-blocks/packages/components/totals/item/style.scss b/plugins/woocommerce-blocks/packages/components/totals/item/style.scss index 3500233949b8..f350a2984da9 100644 --- a/plugins/woocommerce-blocks/packages/components/totals/item/style.scss +++ b/plugins/woocommerce-blocks/packages/components/totals/item/style.scss @@ -11,7 +11,6 @@ .wc-block-components-totals-item__value { font-weight: bold; - white-space: nowrap; } .wc-block-components-totals-item__description { diff --git a/plugins/woocommerce/changelog/45170-add-42004-totalValue-filter b/plugins/woocommerce/changelog/45170-add-42004-totalValue-filter new file mode 100644 index 000000000000..333df2acff7e --- /dev/null +++ b/plugins/woocommerce/changelog/45170-add-42004-totalValue-filter @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add totalValue filter. \ No newline at end of file