Cart block: show products on backorder (https://github.com/woocommerce/woocommerce-blocks/pull/2833)
* Show backorder notice in the Cart block * Don't render variation <div> if empty * Create ProductBackorderNotification component * Add product backorder notification to the checkout block * Fix classname and comment * Rename notification->badge and don't show low stock badge if backorder is shown * Use ternary to dispaly backorder/low stock badge
This commit is contained in:
parent
be513c8875
commit
d894fed1df
|
@ -4,6 +4,7 @@ export { default as FormStep } from './form-step';
|
|||
export { default as OrderSummary } from './order-summary';
|
||||
export { default as PlaceOrderButton } from './place-order-button';
|
||||
export { default as Policies } from './policies';
|
||||
export { default as ProductBackorderBadge } from './product-backorder-badge';
|
||||
export { default as ProductImage } from './product-image';
|
||||
export { default as ProductLowStockBadge } from './product-low-stock-badge';
|
||||
export { default as ProductSummary } from './product-summary';
|
||||
|
|
|
@ -5,6 +5,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|||
import { getCurrency } from '@woocommerce/base-utils';
|
||||
import Label from '@woocommerce/base-components/label';
|
||||
import {
|
||||
ProductBackorderBadge,
|
||||
ProductImage,
|
||||
ProductLowStockBadge,
|
||||
ProductMetadata,
|
||||
|
@ -18,6 +19,7 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
|||
const {
|
||||
images,
|
||||
low_stock_remaining: lowStockRemaining = null,
|
||||
show_backorder_badge: showBackorderBadge = false,
|
||||
name,
|
||||
permalink,
|
||||
prices,
|
||||
|
@ -60,7 +62,15 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
|||
value={ linePrice }
|
||||
/>
|
||||
</div>
|
||||
<ProductLowStockBadge lowStockRemaining={ lowStockRemaining } />
|
||||
{ showBackorderBadge ? (
|
||||
<ProductBackorderBadge />
|
||||
) : (
|
||||
lowStockRemaining && (
|
||||
<ProductLowStockBadge
|
||||
lowStockRemaining={ lowStockRemaining }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
<ProductMetadata
|
||||
shortDescription={ shortDescription }
|
||||
fullDescription={ fullDescription }
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import ProductBadge from '../product-badge';
|
||||
|
||||
/**
|
||||
* Returns a backorder badge.
|
||||
*/
|
||||
const ProductBackorderBadge = () => {
|
||||
return (
|
||||
<ProductBadge className="wc-block-components-product-backorder-badge">
|
||||
{ __( 'Available on backorder', 'woo-gutenberg-products-block' ) }
|
||||
</ProductBadge>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductBackorderBadge;
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
const ProductBadge = ( { children, className } ) => {
|
||||
return (
|
||||
<div
|
||||
className={ classNames(
|
||||
'wc-block-components-product-badge',
|
||||
className
|
||||
) }
|
||||
>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProductBadge.propTypes = {
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default ProductBadge;
|
|
@ -1,4 +1,4 @@
|
|||
.wc-block-components-sale-badge {
|
||||
.wc-block-components-product-badge {
|
||||
@include font-size(smaller);
|
||||
border-radius: 2px;
|
||||
border: 1px solid;
|
|
@ -7,7 +7,7 @@ import PropTypes from 'prop-types';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import ProductBadge from '../product-badge';
|
||||
|
||||
/**
|
||||
* Returns a low stock badge.
|
||||
|
@ -18,13 +18,13 @@ const ProductLowStockBadge = ( { lowStockRemaining } ) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="wc-block-components-product-low-stock-badge">
|
||||
<ProductBadge className="wc-block-components-product-low-stock-badge">
|
||||
{ sprintf(
|
||||
/* translators: %d stock amount (number of items in stock for product) */
|
||||
__( '%d left in stock', 'woo-gutenberg-products-block' ),
|
||||
lowStockRemaining
|
||||
) }
|
||||
</div>
|
||||
</ProductBadge>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
.wc-block-components-product-low-stock-badge {
|
||||
@include font-size(smaller);
|
||||
border-radius: 2px;
|
||||
border: 1px solid;
|
||||
display: inline-block;
|
||||
font-weight: 600;
|
||||
padding: 0 0.66em;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
|
@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import ProductBadge from '../product-badge';
|
||||
|
||||
/**
|
||||
* ProductSaleBadge
|
||||
|
@ -25,7 +25,7 @@ const ProductSaleBadge = ( { currency, saleAmount } ) => {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="wc-block-components-sale-badge">
|
||||
<ProductBadge className="wc-block-components-sale-badge">
|
||||
{ __experimentalCreateInterpolateElement(
|
||||
/* translators: <price/> will be replaced by the discount amount */
|
||||
__( 'Save <price/>', 'woo-gutenberg-products-block' ),
|
||||
|
@ -38,7 +38,7 @@ const ProductSaleBadge = ( { currency, saleAmount } ) => {
|
|||
),
|
||||
}
|
||||
) }
|
||||
</div>
|
||||
</ProductBadge>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import classNames from 'classnames';
|
|||
* Returns a formatted element containing variation details.
|
||||
*/
|
||||
const ProductVariationData = ( { className, variation = [] } ) => {
|
||||
if ( ! variation ) {
|
||||
if ( ! variation || variation.length === 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import { getCurrency } from '@woocommerce/base-utils';
|
|||
import { useStoreCartItemQuantity } from '@woocommerce/base-hooks';
|
||||
import { Icon, trash } from '@woocommerce/icons';
|
||||
import {
|
||||
ProductBackorderBadge,
|
||||
ProductImage,
|
||||
ProductLowStockBadge,
|
||||
ProductMetadata,
|
||||
|
@ -45,6 +46,7 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
|
|||
short_description: shortDescription = '',
|
||||
description: fullDescription = '',
|
||||
low_stock_remaining: lowStockRemaining = null,
|
||||
show_backorder_badge: showBackorderBadge = false,
|
||||
quantity_limit: quantityLimit = 99,
|
||||
permalink = '',
|
||||
images = [],
|
||||
|
@ -111,7 +113,16 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
|
|||
name={ name }
|
||||
disabled={ isPendingDelete }
|
||||
/>
|
||||
<ProductLowStockBadge lowStockRemaining={ lowStockRemaining } />
|
||||
{ showBackorderBadge ? (
|
||||
<ProductBackorderBadge />
|
||||
) : (
|
||||
lowStockRemaining && (
|
||||
<ProductLowStockBadge
|
||||
lowStockRemaining={ lowStockRemaining }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
{ showBackorderBadge && <ProductBackorderBadge /> }
|
||||
<ProductMetadata
|
||||
shortDescription={ shortDescription }
|
||||
fullDescription={ fullDescription }
|
||||
|
|
|
@ -35,6 +35,7 @@ export const previewCart = {
|
|||
permalink: 'https://example.org',
|
||||
low_stock_remaining: 2,
|
||||
backorders_allowed: false,
|
||||
show_backorder_badge: false,
|
||||
sold_individually: false,
|
||||
images: [
|
||||
{
|
||||
|
@ -103,6 +104,7 @@ export const previewCart = {
|
|||
sku: 'woo-cap',
|
||||
permalink: 'https://example.org',
|
||||
backorders_allowed: false,
|
||||
show_backorder_badge: false,
|
||||
sold_individually: false,
|
||||
images: [
|
||||
{
|
||||
|
|
|
@ -143,6 +143,10 @@
|
|||
* @property {boolean} backorders_allowed True if backorders are
|
||||
* allowed past stock
|
||||
* availability.
|
||||
* @property {boolean} show_backorder_badge Whether a notification
|
||||
* should be shown about the
|
||||
* product being available on
|
||||
* backorder.
|
||||
* @property {boolean} sold_individually If true, only one item of
|
||||
* this product is allowed
|
||||
* for purchase in a single
|
||||
|
|
|
@ -45,80 +45,86 @@ class CartItemSchema extends ProductSchema {
|
|||
*/
|
||||
public function get_properties() {
|
||||
return [
|
||||
'key' => [
|
||||
'key' => [
|
||||
'description' => __( 'Unique identifier for the item within the cart.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'id' => [
|
||||
'id' => [
|
||||
'description' => __( 'The cart item product or variation ID.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'integer',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'quantity' => [
|
||||
'quantity' => [
|
||||
'description' => __( 'Quantity of this item in the cart.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'integer',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'quantity_limit' => [
|
||||
'quantity_limit' => [
|
||||
'description' => __( 'The maximum quantity than can be added to the cart at once.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'integer',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'name' => [
|
||||
'name' => [
|
||||
'description' => __( 'Product name.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'short_description' => [
|
||||
'short_description' => [
|
||||
'description' => __( 'Product short description in HTML format.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'description' => [
|
||||
'description' => [
|
||||
'description' => __( 'Product full description in HTML format.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'sku' => [
|
||||
'sku' => [
|
||||
'description' => __( 'Stock keeping unit, if applicable.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'low_stock_remaining' => [
|
||||
'low_stock_remaining' => [
|
||||
'description' => __( 'Quantity left in stock if stock is low, or null if not applicable.', 'woo-gutenberg-products-block' ),
|
||||
'type' => [ 'integer', 'null' ],
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'backorders_allowed' => [
|
||||
'backorders_allowed' => [
|
||||
'description' => __( 'True if backorders are allowed past stock availability.', 'woo-gutenberg-products-block' ),
|
||||
'type' => [ 'boolean' ],
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'sold_individually' => [
|
||||
'show_backorder_badge' => [
|
||||
'description' => __( 'True if the product is on backorder.', 'woo-gutenberg-products-block' ),
|
||||
'type' => [ 'boolean' ],
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'sold_individually' => [
|
||||
'description' => __( 'If true, only one item of this product is allowed for purchase in a single order.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'boolean',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'permalink' => [
|
||||
'permalink' => [
|
||||
'description' => __( 'Product URL.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'format' => 'uri',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'images' => [
|
||||
'images' => [
|
||||
'description' => __( 'List of images.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'array',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
|
@ -128,7 +134,7 @@ class CartItemSchema extends ProductSchema {
|
|||
'properties' => $this->image_attachment_schema->get_properties(),
|
||||
],
|
||||
],
|
||||
'variation' => [
|
||||
'variation' => [
|
||||
'description' => __( 'Chosen attributes (for variations).', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'array',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
|
@ -151,7 +157,7 @@ class CartItemSchema extends ProductSchema {
|
|||
],
|
||||
],
|
||||
],
|
||||
'prices' => [
|
||||
'prices' => [
|
||||
'description' => __( 'Price data for the product in the current line item, including or excluding taxes based on the "display prices during cart and checkout" setting. Provided using the smallest unit of the currency.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'object',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
|
@ -232,7 +238,7 @@ class CartItemSchema extends ProductSchema {
|
|||
]
|
||||
),
|
||||
],
|
||||
'totals' => [
|
||||
'totals' => [
|
||||
'description' => __( 'Item total amounts provided using the smallest unit of the currency.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'object',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
|
@ -280,22 +286,23 @@ class CartItemSchema extends ProductSchema {
|
|||
$product = $cart_item['data'];
|
||||
|
||||
return [
|
||||
'key' => $cart_item['key'],
|
||||
'id' => $product->get_id(),
|
||||
'quantity' => wc_stock_amount( $cart_item['quantity'] ),
|
||||
'quantity_limit' => $this->get_product_quantity_limit( $product ),
|
||||
'name' => $this->prepare_html_response( $product->get_title() ),
|
||||
'short_description' => $this->prepare_html_response( wc_format_content( $product->get_short_description() ) ),
|
||||
'description' => $this->prepare_html_response( wc_format_content( $product->get_description() ) ),
|
||||
'sku' => $this->prepare_html_response( $product->get_sku() ),
|
||||
'low_stock_remaining' => $this->get_low_stock_remaining( $product ),
|
||||
'backorders_allowed' => (bool) $product->backorders_allowed(),
|
||||
'sold_individually' => $product->is_sold_individually(),
|
||||
'permalink' => $product->get_permalink(),
|
||||
'images' => $this->get_images( $product ),
|
||||
'variation' => $this->format_variation_data( $cart_item['variation'], $product ),
|
||||
'prices' => (object) $this->prepare_product_price_response( $product, get_option( 'woocommerce_tax_display_cart' ) ),
|
||||
'totals' => (object) array_merge(
|
||||
'key' => $cart_item['key'],
|
||||
'id' => $product->get_id(),
|
||||
'quantity' => wc_stock_amount( $cart_item['quantity'] ),
|
||||
'quantity_limit' => $this->get_product_quantity_limit( $product ),
|
||||
'name' => $this->prepare_html_response( $product->get_title() ),
|
||||
'short_description' => $this->prepare_html_response( wc_format_content( $product->get_short_description() ) ),
|
||||
'description' => $this->prepare_html_response( wc_format_content( $product->get_description() ) ),
|
||||
'sku' => $this->prepare_html_response( $product->get_sku() ),
|
||||
'low_stock_remaining' => $this->get_low_stock_remaining( $product ),
|
||||
'backorders_allowed' => (bool) $product->backorders_allowed(),
|
||||
'show_backorder_badge' => (bool) $product->backorders_require_notification() && $product->is_on_backorder( $cart_item['quantity'] ),
|
||||
'sold_individually' => $product->is_sold_individually(),
|
||||
'permalink' => $product->get_permalink(),
|
||||
'images' => $this->get_images( $product ),
|
||||
'variation' => $this->format_variation_data( $cart_item['variation'], $product ),
|
||||
'prices' => (object) $this->prepare_product_price_response( $product, get_option( 'woocommerce_tax_display_cart' ) ),
|
||||
'totals' => (object) array_merge(
|
||||
$this->get_store_currency_response(),
|
||||
[
|
||||
'line_subtotal' => $this->prepare_money_response( $cart_item['line_subtotal'], wc_get_price_decimals() ),
|
||||
|
|
|
@ -35,6 +35,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items"
|
|||
"sku": "woo-beanie",
|
||||
"low_stock_remaining": null,
|
||||
"backorders_allowed": false,
|
||||
"show_backorder_badge": false,
|
||||
"sold_individually": false,
|
||||
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
||||
"images": [
|
||||
|
@ -106,6 +107,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items"
|
|||
"sku": "wp-pennant",
|
||||
"low_stock_remaining": null,
|
||||
"backorders_allowed": false,
|
||||
"show_backorder_badge": false,
|
||||
"sold_individually": false,
|
||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||
"images": [
|
||||
|
@ -199,6 +201,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items/e369853df766fa44e1ed
|
|||
"sku": "wp-pennant",
|
||||
"low_stock_remaining": null,
|
||||
"backorders_allowed": false,
|
||||
"show_backorder_badge": false,
|
||||
"sold_individually": false,
|
||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||
"images": [
|
||||
|
|
|
@ -115,6 +115,7 @@ All endpoints under `/cart` (listed in this doc) return responses in the same fo
|
|||
"sku": "woo-beanie",
|
||||
"low_stock_remaining": null,
|
||||
"backorders_allowed": false,
|
||||
"show_backorder_badge": false,
|
||||
"sold_individually": false,
|
||||
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
||||
"images": [
|
||||
|
@ -174,6 +175,7 @@ All endpoints under `/cart` (listed in this doc) return responses in the same fo
|
|||
"sku": "wp-pennant",
|
||||
"low_stock_remaining": null,
|
||||
"backorders_allowed": false,
|
||||
"show_backorder_badge": false,
|
||||
"sold_individually": false,
|
||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||
"images": [
|
||||
|
|
|
@ -229,6 +229,7 @@ class CartItems extends TestCase {
|
|||
$this->assertArrayHasKey( 'variation', $data );
|
||||
$this->assertArrayHasKey( 'low_stock_remaining', $data );
|
||||
$this->assertArrayHasKey( 'backorders_allowed', $data );
|
||||
$this->assertArrayHasKey( 'show_backorder_badge', $data );
|
||||
$this->assertArrayHasKey( 'short_description', $data );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue