/** * External dependencies */ import { Component } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { withDispatch, withSelect } from '@wordpress/data'; import PropTypes from 'prop-types'; import { Section } from '@woocommerce/components'; import { ITEMS_STORE_NAME } from '@woocommerce/data'; /** * Internal dependencies */ import { ActivityCardPlaceholder } from '~/activity-panel/activity-card'; import { ProductStockCard } from './card'; import { getLowStockCountQuery } from '../orders/utils'; const productsQuery = { page: 1, per_page: 5, status: 'publish', _fields: [ 'attributes', 'id', 'images', 'last_order_date', 'low_stock_amount', 'name', 'parent_id', 'stock_quantity', 'type', ], }; export class StockPanel extends Component { constructor( props ) { super( props ); this.updateStock = this.updateStock.bind( this ); } async updateStock( product, quantity ) { const { invalidateResolution, updateProductStock } = this.props; const success = await updateProductStock( product, quantity ); if ( success ) { // Request more low stock products. invalidateResolution( 'getItems', [ 'products/low-in-stock', productsQuery, ] ); invalidateResolution( 'getItemsTotalCount', [ 'products/count-low-in-stock', getLowStockCountQuery, null, ] ); } return success; } renderProducts() { const { products, createNotice } = this.props; return products.map( ( product ) => ( ) ); } render() { const { lowStockProductsCount, isError, isRequesting, products } = this.props; if ( isError ) { throw new Error( 'Failed to load low stock products, Raise error to trigger ErrorBoundary' ); } // Show placeholders only for the first products fetch. if ( isRequesting || ! products.length ) { const numPlaceholders = Math.min( 5, lowStockProductsCount ?? 1 ); const placeholders = Array.from( new Array( numPlaceholders ) ).map( ( v, idx ) => ( ) ); return
{ placeholders }
; } return
{ this.renderProducts() }
; } } StockPanel.propTypes = { lowStockProductsCount: PropTypes.number, products: PropTypes.array.isRequired, isError: PropTypes.bool, isRequesting: PropTypes.bool, }; StockPanel.defaultProps = { products: [], isError: false, isRequesting: false, }; export default compose( withSelect( ( select ) => { const { getItems, getItemsError, isResolving } = select( ITEMS_STORE_NAME ); const products = Array.from( getItems( 'products/low-in-stock', productsQuery ).values() ); const isError = Boolean( getItemsError( 'products/low-in-stock', productsQuery ) ); const isRequesting = isResolving( 'getItems', [ 'products/low-in-stock', productsQuery, ] ); return { products, isError, isRequesting }; } ), withDispatch( ( dispatch ) => { const { invalidateResolution, updateProductStock } = dispatch( ITEMS_STORE_NAME ); const { createNotice } = dispatch( 'core/notices' ); return { createNotice, invalidateResolution, updateProductStock, }; } ) )( StockPanel );