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 OrderSummary } from './order-summary';
|
||||||
export { default as PlaceOrderButton } from './place-order-button';
|
export { default as PlaceOrderButton } from './place-order-button';
|
||||||
export { default as Policies } from './policies';
|
export { default as Policies } from './policies';
|
||||||
|
export { default as ProductBackorderBadge } from './product-backorder-badge';
|
||||||
export { default as ProductImage } from './product-image';
|
export { default as ProductImage } from './product-image';
|
||||||
export { default as ProductLowStockBadge } from './product-low-stock-badge';
|
export { default as ProductLowStockBadge } from './product-low-stock-badge';
|
||||||
export { default as ProductSummary } from './product-summary';
|
export { default as ProductSummary } from './product-summary';
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { getCurrency } from '@woocommerce/base-utils';
|
import { getCurrency } from '@woocommerce/base-utils';
|
||||||
import Label from '@woocommerce/base-components/label';
|
import Label from '@woocommerce/base-components/label';
|
||||||
import {
|
import {
|
||||||
|
ProductBackorderBadge,
|
||||||
ProductImage,
|
ProductImage,
|
||||||
ProductLowStockBadge,
|
ProductLowStockBadge,
|
||||||
ProductMetadata,
|
ProductMetadata,
|
||||||
|
@ -18,6 +19,7 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
||||||
const {
|
const {
|
||||||
images,
|
images,
|
||||||
low_stock_remaining: lowStockRemaining = null,
|
low_stock_remaining: lowStockRemaining = null,
|
||||||
|
show_backorder_badge: showBackorderBadge = false,
|
||||||
name,
|
name,
|
||||||
permalink,
|
permalink,
|
||||||
prices,
|
prices,
|
||||||
|
@ -60,7 +62,15 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
||||||
value={ linePrice }
|
value={ linePrice }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ProductLowStockBadge lowStockRemaining={ lowStockRemaining } />
|
{ showBackorderBadge ? (
|
||||||
|
<ProductBackorderBadge />
|
||||||
|
) : (
|
||||||
|
lowStockRemaining && (
|
||||||
|
<ProductLowStockBadge
|
||||||
|
lowStockRemaining={ lowStockRemaining }
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
) }
|
||||||
<ProductMetadata
|
<ProductMetadata
|
||||||
shortDescription={ shortDescription }
|
shortDescription={ shortDescription }
|
||||||
fullDescription={ fullDescription }
|
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);
|
@include font-size(smaller);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
|
@ -7,7 +7,7 @@ import PropTypes from 'prop-types';
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import './style.scss';
|
import ProductBadge from '../product-badge';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a low stock badge.
|
* Returns a low stock badge.
|
||||||
|
@ -18,13 +18,13 @@ const ProductLowStockBadge = ( { lowStockRemaining } ) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wc-block-components-product-low-stock-badge">
|
<ProductBadge className="wc-block-components-product-low-stock-badge">
|
||||||
{ sprintf(
|
{ sprintf(
|
||||||
/* translators: %d stock amount (number of items in stock for product) */
|
/* translators: %d stock amount (number of items in stock for product) */
|
||||||
__( '%d left in stock', 'woo-gutenberg-products-block' ),
|
__( '%d left in stock', 'woo-gutenberg-products-block' ),
|
||||||
lowStockRemaining
|
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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import './style.scss';
|
import ProductBadge from '../product-badge';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ProductSaleBadge
|
* ProductSaleBadge
|
||||||
|
@ -25,7 +25,7 @@ const ProductSaleBadge = ( { currency, saleAmount } ) => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="wc-block-components-sale-badge">
|
<ProductBadge className="wc-block-components-sale-badge">
|
||||||
{ __experimentalCreateInterpolateElement(
|
{ __experimentalCreateInterpolateElement(
|
||||||
/* translators: <price/> will be replaced by the discount amount */
|
/* translators: <price/> will be replaced by the discount amount */
|
||||||
__( 'Save <price/>', 'woo-gutenberg-products-block' ),
|
__( '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.
|
* Returns a formatted element containing variation details.
|
||||||
*/
|
*/
|
||||||
const ProductVariationData = ( { className, variation = [] } ) => {
|
const ProductVariationData = ( { className, variation = [] } ) => {
|
||||||
if ( ! variation ) {
|
if ( ! variation || variation.length === 0 ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { getCurrency } from '@woocommerce/base-utils';
|
||||||
import { useStoreCartItemQuantity } from '@woocommerce/base-hooks';
|
import { useStoreCartItemQuantity } from '@woocommerce/base-hooks';
|
||||||
import { Icon, trash } from '@woocommerce/icons';
|
import { Icon, trash } from '@woocommerce/icons';
|
||||||
import {
|
import {
|
||||||
|
ProductBackorderBadge,
|
||||||
ProductImage,
|
ProductImage,
|
||||||
ProductLowStockBadge,
|
ProductLowStockBadge,
|
||||||
ProductMetadata,
|
ProductMetadata,
|
||||||
|
@ -45,6 +46,7 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
|
||||||
short_description: shortDescription = '',
|
short_description: shortDescription = '',
|
||||||
description: fullDescription = '',
|
description: fullDescription = '',
|
||||||
low_stock_remaining: lowStockRemaining = null,
|
low_stock_remaining: lowStockRemaining = null,
|
||||||
|
show_backorder_badge: showBackorderBadge = false,
|
||||||
quantity_limit: quantityLimit = 99,
|
quantity_limit: quantityLimit = 99,
|
||||||
permalink = '',
|
permalink = '',
|
||||||
images = [],
|
images = [],
|
||||||
|
@ -111,7 +113,16 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
|
||||||
name={ name }
|
name={ name }
|
||||||
disabled={ isPendingDelete }
|
disabled={ isPendingDelete }
|
||||||
/>
|
/>
|
||||||
<ProductLowStockBadge lowStockRemaining={ lowStockRemaining } />
|
{ showBackorderBadge ? (
|
||||||
|
<ProductBackorderBadge />
|
||||||
|
) : (
|
||||||
|
lowStockRemaining && (
|
||||||
|
<ProductLowStockBadge
|
||||||
|
lowStockRemaining={ lowStockRemaining }
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
) }
|
||||||
|
{ showBackorderBadge && <ProductBackorderBadge /> }
|
||||||
<ProductMetadata
|
<ProductMetadata
|
||||||
shortDescription={ shortDescription }
|
shortDescription={ shortDescription }
|
||||||
fullDescription={ fullDescription }
|
fullDescription={ fullDescription }
|
||||||
|
|
|
@ -35,6 +35,7 @@ export const previewCart = {
|
||||||
permalink: 'https://example.org',
|
permalink: 'https://example.org',
|
||||||
low_stock_remaining: 2,
|
low_stock_remaining: 2,
|
||||||
backorders_allowed: false,
|
backorders_allowed: false,
|
||||||
|
show_backorder_badge: false,
|
||||||
sold_individually: false,
|
sold_individually: false,
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
|
@ -103,6 +104,7 @@ export const previewCart = {
|
||||||
sku: 'woo-cap',
|
sku: 'woo-cap',
|
||||||
permalink: 'https://example.org',
|
permalink: 'https://example.org',
|
||||||
backorders_allowed: false,
|
backorders_allowed: false,
|
||||||
|
show_backorder_badge: false,
|
||||||
sold_individually: false,
|
sold_individually: false,
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,6 +143,10 @@
|
||||||
* @property {boolean} backorders_allowed True if backorders are
|
* @property {boolean} backorders_allowed True if backorders are
|
||||||
* allowed past stock
|
* allowed past stock
|
||||||
* availability.
|
* 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
|
* @property {boolean} sold_individually If true, only one item of
|
||||||
* this product is allowed
|
* this product is allowed
|
||||||
* for purchase in a single
|
* for purchase in a single
|
||||||
|
|
|
@ -105,6 +105,12 @@ class CartItemSchema extends ProductSchema {
|
||||||
'context' => [ 'view', 'edit' ],
|
'context' => [ 'view', 'edit' ],
|
||||||
'readonly' => true,
|
'readonly' => true,
|
||||||
],
|
],
|
||||||
|
'show_backorder_badge' => [
|
||||||
|
'description' => __( 'True if the product is on backorder.', 'woo-gutenberg-products-block' ),
|
||||||
|
'type' => [ 'boolean' ],
|
||||||
|
'context' => [ 'view', 'edit' ],
|
||||||
|
'readonly' => true,
|
||||||
|
],
|
||||||
'sold_individually' => [
|
'sold_individually' => [
|
||||||
'description' => __( 'If true, only one item of this product is allowed for purchase in a single order.', 'woo-gutenberg-products-block' ),
|
'description' => __( 'If true, only one item of this product is allowed for purchase in a single order.', 'woo-gutenberg-products-block' ),
|
||||||
'type' => 'boolean',
|
'type' => 'boolean',
|
||||||
|
@ -290,6 +296,7 @@ class CartItemSchema extends ProductSchema {
|
||||||
'sku' => $this->prepare_html_response( $product->get_sku() ),
|
'sku' => $this->prepare_html_response( $product->get_sku() ),
|
||||||
'low_stock_remaining' => $this->get_low_stock_remaining( $product ),
|
'low_stock_remaining' => $this->get_low_stock_remaining( $product ),
|
||||||
'backorders_allowed' => (bool) $product->backorders_allowed(),
|
'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(),
|
'sold_individually' => $product->is_sold_individually(),
|
||||||
'permalink' => $product->get_permalink(),
|
'permalink' => $product->get_permalink(),
|
||||||
'images' => $this->get_images( $product ),
|
'images' => $this->get_images( $product ),
|
||||||
|
|
|
@ -35,6 +35,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items"
|
||||||
"sku": "woo-beanie",
|
"sku": "woo-beanie",
|
||||||
"low_stock_remaining": null,
|
"low_stock_remaining": null,
|
||||||
"backorders_allowed": false,
|
"backorders_allowed": false,
|
||||||
|
"show_backorder_badge": false,
|
||||||
"sold_individually": false,
|
"sold_individually": false,
|
||||||
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
||||||
"images": [
|
"images": [
|
||||||
|
@ -106,6 +107,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items"
|
||||||
"sku": "wp-pennant",
|
"sku": "wp-pennant",
|
||||||
"low_stock_remaining": null,
|
"low_stock_remaining": null,
|
||||||
"backorders_allowed": false,
|
"backorders_allowed": false,
|
||||||
|
"show_backorder_badge": false,
|
||||||
"sold_individually": false,
|
"sold_individually": false,
|
||||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||||
"images": [
|
"images": [
|
||||||
|
@ -199,6 +201,7 @@ curl "https://example-store.com/wp-json/wc/store/cart/items/e369853df766fa44e1ed
|
||||||
"sku": "wp-pennant",
|
"sku": "wp-pennant",
|
||||||
"low_stock_remaining": null,
|
"low_stock_remaining": null,
|
||||||
"backorders_allowed": false,
|
"backorders_allowed": false,
|
||||||
|
"show_backorder_badge": false,
|
||||||
"sold_individually": false,
|
"sold_individually": false,
|
||||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||||
"images": [
|
"images": [
|
||||||
|
|
|
@ -115,6 +115,7 @@ All endpoints under `/cart` (listed in this doc) return responses in the same fo
|
||||||
"sku": "woo-beanie",
|
"sku": "woo-beanie",
|
||||||
"low_stock_remaining": null,
|
"low_stock_remaining": null,
|
||||||
"backorders_allowed": false,
|
"backorders_allowed": false,
|
||||||
|
"show_backorder_badge": false,
|
||||||
"sold_individually": false,
|
"sold_individually": false,
|
||||||
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
"permalink": "https:\/\/local.wordpress.test\/product\/beanie\/",
|
||||||
"images": [
|
"images": [
|
||||||
|
@ -174,6 +175,7 @@ All endpoints under `/cart` (listed in this doc) return responses in the same fo
|
||||||
"sku": "wp-pennant",
|
"sku": "wp-pennant",
|
||||||
"low_stock_remaining": null,
|
"low_stock_remaining": null,
|
||||||
"backorders_allowed": false,
|
"backorders_allowed": false,
|
||||||
|
"show_backorder_badge": false,
|
||||||
"sold_individually": false,
|
"sold_individually": false,
|
||||||
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
"permalink": "https:\/\/local.wordpress.test\/product\/wordpress-pennant\/",
|
||||||
"images": [
|
"images": [
|
||||||
|
|
|
@ -229,6 +229,7 @@ class CartItems extends TestCase {
|
||||||
$this->assertArrayHasKey( 'variation', $data );
|
$this->assertArrayHasKey( 'variation', $data );
|
||||||
$this->assertArrayHasKey( 'low_stock_remaining', $data );
|
$this->assertArrayHasKey( 'low_stock_remaining', $data );
|
||||||
$this->assertArrayHasKey( 'backorders_allowed', $data );
|
$this->assertArrayHasKey( 'backorders_allowed', $data );
|
||||||
|
$this->assertArrayHasKey( 'show_backorder_badge', $data );
|
||||||
$this->assertArrayHasKey( 'short_description', $data );
|
$this->assertArrayHasKey( 'short_description', $data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue