diff --git a/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/block.json b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/block.json new file mode 100644 index 00000000000..bd489fa977e --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/block.json @@ -0,0 +1,46 @@ +{ + "name": "woocommerce/collection-stock-filter", + "version": "1.0.0", + "title": "Stock Filter", + "description": "Enable customers to filter the product collection by stock status.", + "category": "woocommerce", + "keywords": [ "WooCommerce", "filter", "stock" ], + "supports": { + "interactivity": true, + "html": false, + "multiple": false + }, + "attributes": { + "className": { + "type": "string", + "default": "" + }, + "showCounts": { + "type": "boolean", + "default": false + }, + "displayStyle": { + "type": "string", + "default": "list" + }, + "selectType": { + "type": "string", + "default": "multiple" + }, + "isPreview": { + "type": "boolean", + "default": false + }, + "queryParam": { + "type": "object", + "default": { + "calculate_stock_status_counts": "true" + } + } + }, + "usesContext": [ "collectionData" ], + "ancestor": [ "woocommerce/collection-filters" ], + "textdomain": "woo-gutenberg-products-block", + "apiVersion": 2, + "$schema": "https://schemas.wp.org/trunk/block.json" +} diff --git a/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/components/inspector.tsx b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/components/inspector.tsx new file mode 100644 index 00000000000..973a125e052 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/components/inspector.tsx @@ -0,0 +1,96 @@ +/** + * External dependencies + */ +import { InspectorControls } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { + PanelBody, + ToggleControl, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalToggleGroupControl as ToggleGroupControl, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalToggleGroupControlOption as ToggleGroupControlOption, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { EditProps } from '../types'; + +export const Inspector = ( { attributes, setAttributes }: EditProps ) => { + const { showCounts, selectType, displayStyle } = attributes; + + return ( + + + + setAttributes( { + showCounts: ! showCounts, + } ) + } + /> + + setAttributes( { + selectType: value, + } ) + } + className="wc-block-attribute-filter__multiple-toggle" + > + + + + + setAttributes( { + displayStyle: value, + } ) + } + className="wc-block-attribute-filter__display-toggle" + > + + + + + + ); +}; diff --git a/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/edit.tsx b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/edit.tsx new file mode 100644 index 00000000000..de7bfc23242 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/blocks/collection-filters/inner-blocks/stock-filter/edit.tsx @@ -0,0 +1,131 @@ +/** + * External dependencies + */ +import { useMemo } from '@wordpress/element'; +import classnames from 'classnames'; +import { useBlockProps } from '@wordpress/block-editor'; +import { Disabled } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { Icon, chevronDown } from '@wordpress/icons'; +import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types'; +import { CheckboxList } from '@woocommerce/blocks-components'; +import Label from '@woocommerce/base-components/filter-element-label'; +import FormTokenField from '@woocommerce/base-components/form-token-field'; +import type { BlockEditProps } from '@wordpress/blocks'; +import { getSetting } from '@woocommerce/settings'; +import { + useCollectionData, + useQueryStateByContext, +} from '@woocommerce/base-context/hooks'; + +/** + * Internal dependencies + */ +import { BlockProps } from './types'; +import { Inspector } from './components/inspector'; + +type CollectionData = { + // attribute_counts: null | unknown; + // price_range: null | unknown; + // rating_counts: null | unknown; + stock_status_counts: StockStatusCount[]; +}; + +type StockStatusCount = { + status: string; + count: number; +}; + +const Edit = ( props: BlockEditProps< BlockProps > & { context: Context } ) => { + const blockProps = useBlockProps( { + className: classnames( + 'wc-block-stock-filter', + props.attributes.className + ), + } ); + + const { showCounts, displayStyle } = props.attributes; + const stockStatusOptions: Record< string, string > = getSetting( + 'stockStatusOptions', + {} + ); + + const [ queryState ] = useQueryStateByContext(); + + const { results: filteredCounts } = useCollectionData( { + queryStock: true, + queryState, + isEditor: true, + } ); + + const listOptions = useMemo( () => { + return Object.entries( stockStatusOptions ).map( ( [ key, value ] ) => { + const count = + // @ts-expect-error - there is a fault with useCollectionData types, it can be non-array. + ( filteredCounts as CollectionData )?.stock_status_counts?.find( + ( item: StockStatusCount ) => item.status === key + )?.count; + + return { + value: key, + label: ( +