From 76ebf9c860a9ac9f06e9577763f1e1dd34f0afd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= Date: Mon, 14 Sep 2020 12:56:10 +0200 Subject: [PATCH] Merge ProductPrice atomic block and component (https://github.com/woocommerce/woocommerce-blocks/pull/3065) * Merge ProductPrice atomic block and component * Update assets/js/atomic/blocks/product-elements/price/block.js Co-authored-by: Darren Ethier * Update assets/js/atomic/blocks/product-elements/price/block.js Co-authored-by: Darren Ethier * If product price component has alignment, make it a block * Make ProductPrice propTypes more specific * Add align prop to loading product price * Add stories to ProductPrice component Co-authored-by: Darren Ethier --- .../blocks/product-elements/price/block.js | 197 ++++-------------- .../js/base/components/cart-checkout/index.js | 1 - .../order-summary/order-summary-item.js | 6 +- .../cart-checkout/product-name/index.js | 3 +- .../cart-checkout/product-price/index.js | 81 ------- .../cart-checkout/product-price/style.scss | 5 - .../js/base/components/product-price/index.js | 196 +++++++++++++++++ .../components/product-price/stories/index.js | 82 ++++++++ .../components/product-price}/style.scss | 9 + .../cart/full-cart/cart-line-item-row.js | 6 +- 10 files changed, 333 insertions(+), 253 deletions(-) delete mode 100644 plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js delete mode 100644 plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/product-price/index.js create mode 100644 plugins/woocommerce-blocks/assets/js/base/components/product-price/stories/index.js rename plugins/woocommerce-blocks/assets/js/{atomic/blocks/product-elements/price => base/components/product-price}/style.scss (73%) diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/block.js b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/block.js index 142e894ae17..93286f37e80 100644 --- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/block.js +++ b/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/block.js @@ -3,7 +3,7 @@ */ import PropTypes from 'prop-types'; import classnames from 'classnames'; -import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; +import ProductPrice from '@woocommerce/base-components/product-price'; import { getCurrencyFromPriceResponse } from '@woocommerce/base-utils'; import { useInnerBlockLayoutContext, @@ -13,11 +13,6 @@ import { getColorClassName, getFontSizeClass } from '@wordpress/block-editor'; import { isFeaturePluginBuild } from '@woocommerce/block-settings'; import { withProductDataContext } from '@woocommerce/shared-hocs'; -/** - * Internal dependencies - */ -import './style.scss'; - /** * Product Price Block Component. * @@ -51,6 +46,14 @@ const Block = ( { const { parentClassName } = useInnerBlockLayoutContext(); const { product } = useProductDataContext(); + const wrapperClassName = classnames( className, { + [ `${ parentClassName }__product-price` ]: parentClassName, + } ); + + if ( ! product.id ) { + return ; + } + const colorClass = getColorClassName( 'color', color ); const fontSizeClass = getFontSizeClass( fontSize ); const saleColorClass = getColorClassName( 'color', saleColor ); @@ -80,163 +83,39 @@ const Block = ( { fontSize: customSaleFontSize, }; - if ( ! product.id ) { - return ( -
- ); - } - const prices = product.prices; const currency = getCurrencyFromPriceResponse( prices ); + const isOnSale = prices.price !== prices.regular_price; + const priceClassName = isOnSale + ? classnames( { + [ `${ parentClassName }__product-price__value` ]: parentClassName, + [ saleClasses ]: isFeaturePluginBuild(), + } ) + : classnames( { + [ `${ parentClassName }__product-price__value` ]: parentClassName, + [ classes ]: isFeaturePluginBuild(), + } ); + const priceStyle = isOnSale ? saleStyle : style; return ( -
- { /* eslint-disable-next-line no-nested-ternary */ } - { hasPriceRange( prices ) ? ( - - ) : prices.price !== prices.regular_price ? ( - - ) : ( - - ) } -
- ); -}; - -const hasPriceRange = ( prices ) => { - return ( - prices.price_range && - prices.price_range.min_amount && - prices.price_range.max_amount - ); -}; - -const PriceRange = ( { currency, minAmount, maxAmount, classes, style } ) => { - const { parentClassName } = useInnerBlockLayoutContext(); - - return ( - - -  —  - - - ); -}; - -const SalePrice = ( { - currency, - price, - regularPrice, - saleClasses = '', - saleStyle = {}, - classes = '', - style = {}, -} ) => { - const { parentClassName } = useInnerBlockLayoutContext(); - return ( - <> - - - - - - - - ); -}; - -const Price = ( { currency, price, classes = '', style = {} } ) => { - const { parentClassName } = useInnerBlockLayoutContext(); - return ( - - - + ); }; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/index.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/index.js index cc8c82bfad8..8c023666abd 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/index.js @@ -9,7 +9,6 @@ export { default as ProductLowStockBadge } from './product-low-stock-badge'; export { default as ProductSummary } from './product-summary'; export { default as ProductMetadata } from './product-metadata'; export { default as ProductName } from './product-name'; -export { default as ProductPrice } from './product-price'; export { default as ProductSaleBadge } from './product-sale-badge'; export { default as ProductVariationData } from './product-variation-data'; export { default as ReturnToCartButton } from './return-to-cart-button'; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.js index ba112f5b2ea..8e9157c99c1 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/order-summary/order-summary-item.js @@ -4,13 +4,13 @@ import { __, sprintf } from '@wordpress/i18n'; import { getCurrency } from '@woocommerce/base-utils'; import Label from '@woocommerce/base-components/label'; +import ProductPrice from '@woocommerce/base-components/product-price'; import { ProductBackorderBadge, ProductImage, ProductLowStockBadge, ProductMetadata, ProductName, - ProductPrice, } from '@woocommerce/base-components/cart-checkout'; import PropTypes from 'prop-types'; import Dinero from 'dinero.js'; @@ -57,9 +57,9 @@ const OrderSummaryItem = ( { cartItem } ) => {
{ showBackorderBadge ? ( diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-name/index.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-name/index.js index 698142d7afa..33711fa3442 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-name/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-name/index.js @@ -9,7 +9,7 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import './style.scss'; -const ProductName = ( { name, permalink, disabled } ) => { +const ProductName = ( { name, permalink, disabled = false } ) => { return ( // we use tabIndex -1 to prevent the link from being focused, pointer-events // disabled click events, so we get an almost disabled link. @@ -24,6 +24,7 @@ const ProductName = ( { name, permalink, disabled } ) => { }; ProductName.propTypes = { + disabled: PropTypes.bool, name: PropTypes.string, permalink: PropTypes.string, }; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js deleted file mode 100644 index aac35707fbf..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * External dependencies - */ -import { __ } from '@wordpress/i18n'; -import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; -import classNames from 'classnames'; -import PropTypes from 'prop-types'; - -/** - * Internal dependencies - */ -import './style.scss'; - -const ProductPrice = ( { className, currency, regularValue, value } ) => { - const isDiscounted = - Number.isFinite( regularValue ) && regularValue > value; - - if ( isDiscounted ) { - return ( - - - { __( 'Previous price:', 'woo-gutenberg-products-block' ) } - - - - - - { __( - 'Discounted price:', - 'woo-gutenberg-products-block' - ) } - - - - - - ); - } - - return ( - - - - ); -}; - -ProductPrice.propTypes = { - currency: PropTypes.object.isRequired, - value: PropTypes.number.isRequired, - className: PropTypes.string, - regularValue: PropTypes.number, -}; - -export default ProductPrice; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss deleted file mode 100644 index 275ca8c56cb..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss +++ /dev/null @@ -1,5 +0,0 @@ -.wc-block-components-product-price__value { - &.is-discounted { - margin-left: 0.5em; - } -} diff --git a/plugins/woocommerce-blocks/assets/js/base/components/product-price/index.js b/plugins/woocommerce-blocks/assets/js/base/components/product-price/index.js new file mode 100644 index 00000000000..b9c4e13c3b0 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/product-price/index.js @@ -0,0 +1,196 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; + +/** + * Internal dependencies + */ +import './style.scss'; + +const PriceRange = ( { + className, + currency, + maxPrice, + minPrice, + priceClassName, + priceStyle, +} ) => { + return ( + + +  —  + + + ); +}; + +const SalePrice = ( { + className, + currency, + regularPriceClassName, + regularPriceStyle, + regularPrice, + priceClassName, + priceStyle, + price, +} ) => { + return ( + + + { __( 'Previous price:', 'woo-gutenberg-products-block' ) } + + ( + + { value } + + ) } + value={ regularPrice } + /> + + { __( 'Discounted price:', 'woo-gutenberg-products-block' ) } + + ( + + { value } + + ) } + value={ price } + /> + + ); +}; + +const ProductPrice = ( { + align, + className, + currency, + maxPrice = null, + minPrice = null, + price = null, + priceClassName, + priceStyle, + regularPrice, + regularPriceClassName, + regularPriceStyle, +} ) => { + const wrapperClassName = classNames( + className, + 'price', + 'wc-block-components-product-price', + { + [ `wc-block-components-product-price--align-${ align }` ]: align, + } + ); + + const isDiscounted = regularPrice && price !== regularPrice; + + if ( isDiscounted ) { + return ( + + ); + } + + if ( minPrice !== null && maxPrice !== null ) { + return ( + + ); + } + + if ( price !== null ) { + return ( + + + + ); + } + + return ( + + + + ); +}; + +ProductPrice.propTypes = { + align: PropTypes.oneOf( [ 'left', 'center', 'right' ] ), + className: PropTypes.string, + currency: PropTypes.object, + price: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ), + priceClassName: PropTypes.string, + priceStyle: PropTypes.object, + // Range price props + maxPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ), + minPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ), + // On sale price props + regularPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ), + regularPriceClassName: PropTypes.string, + regularPriceStyle: PropTypes.object, +}; + +export default ProductPrice; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/product-price/stories/index.js b/plugins/woocommerce-blocks/assets/js/base/components/product-price/stories/index.js new file mode 100644 index 00000000000..b442bdd4572 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/product-price/stories/index.js @@ -0,0 +1,82 @@ +/** + * External dependencies + */ +import { number, select } from '@storybook/addon-knobs'; + +/** + * Internal dependencies + */ +import ProductPrice from '../'; + +export default { + title: 'WooCommerce Blocks/@base-components/ProductPrice', + component: ProductPrice, +}; + +const getKnobs = () => { + const align = select( 'Align', [ 'left', 'center', 'right' ], 'left' ); + const currencies = [ + { + label: 'USD', + code: 'USD', + symbol: '$', + thousandSeparator: ',', + decimalSeparator: '.', + minorUnit: 2, + prefix: '$', + suffix: '', + }, + { + label: 'EUR', + code: 'EUR', + symbol: '€', + thousandSeparator: '.', + decimalSeparator: ',', + minorUnit: 2, + prefix: '', + suffix: '€', + }, + ]; + const currency = select( 'Currency', currencies, currencies[ 0 ] ); + + return { align, currency }; +}; + +export const standard = () => { + const { align, currency } = getKnobs(); + const price = number( 'Price', 4000 ); + + return ( + + ); +}; + +export const sale = () => { + const { align, currency } = getKnobs(); + const price = number( 'Price', 3000 ); + const regularPrice = number( 'Regular price', 4000 ); + + return ( + + ); +}; + +export const range = () => { + const { align, currency } = getKnobs(); + const minPrice = number( 'Min price', 3000 ); + const maxPrice = number( 'Max price', 5000 ); + + return ( + + ); +}; diff --git a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/product-price/style.scss similarity index 73% rename from plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/style.scss rename to plugins/woocommerce-blocks/assets/js/base/components/product-price/style.scss index d82226dd694..e3b7db30178 100644 --- a/plugins/woocommerce-blocks/assets/js/atomic/blocks/product-elements/price/style.scss +++ b/plugins/woocommerce-blocks/assets/js/base/components/product-price/style.scss @@ -1,15 +1,24 @@ /*rtl:begin:ignore*/ .wc-block-components-product-price--align-left { + display: block; text-align: left; } .wc-block-components-product-price--align-center { + display: block; text-align: center; } .wc-block-components-product-price--align-right { + display: block; text-align: right; } /*rtl:end:ignore*/ +.wc-block-components-product-price__value { + &.is-discounted { + margin-left: 0.5em; + } +} + .is-loading { .wc-block-components-product-price::before { @include placeholder(); diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js index 513f6e2fea4..171e8ea57b9 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js @@ -5,6 +5,7 @@ import classnames from 'classnames'; import { __ } from '@wordpress/i18n'; import PropTypes from 'prop-types'; import QuantitySelector from '@woocommerce/base-components/quantity-selector'; +import ProductPrice from '@woocommerce/base-components/product-price'; import { getCurrency } from '@woocommerce/base-utils'; import { useStoreCartItemQuantity } from '@woocommerce/base-hooks'; import { Icon, trash } from '@woocommerce/icons'; @@ -14,7 +15,6 @@ import { ProductLowStockBadge, ProductMetadata, ProductName, - ProductPrice, ProductSaleBadge, } from '@woocommerce/base-components/cart-checkout'; import Dinero from 'dinero.js'; @@ -156,11 +156,11 @@ const CartLineItemRow = ( { lineItem = {} } ) => {