This repository has been archived by the owner on Feb 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Product Collection: Hand picked products control in sidebar settings (#…
…9733) * Add support for hand-picked products in Product Collection block This commit introduces the ability to manually select specific products in the Product Collection block. Changes include: - Added `woocommerceHandPickedProducts` to the `ProductCollectionQuery` and `DEFAULT_FILTERS` in `constants.ts`. - Created a new control file `hand-picked-products-control.tsx` which introduces a token field where the user can search for and select specific products. - Included `HandPickedProductsControl` in the Product Collection block's inspector controls in `index.tsx`. - Updated `ProductCollectionQuery` in `types.ts` to accommodate handpicked products. - Updated the PHP `ProductCollection` class to handle the hand-picked products query parameters. These changes allow users to hand-pick products to be displayed in the Product Collection block. This allows for greater customization of the products shown in the block. * Enhance handling of hand-picked products - A Set data structure is now used to store 'newHandPickedProducts' instead of an Array, which will help prevent duplicate entries. - Additionally, the suggestions for products to be hand-picked now excludes already selected products, enhancing the user experience by avoiding redundancy in the suggestions list. - Lastly, the function name 'displayTransform' has been changed to 'transformTokenIntoProductName' to more accurately reflect its purpose, which is to transform a token into a product name. * Update import & export of HandPickedProductsControl
- Loading branch information
1 parent
1242940
commit 3fb911b
Showing
5 changed files
with
206 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
assets/js/blocks/product-collection/inspector-controls/hand-picked-products-control.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { getProducts } from '@woocommerce/editor-components/utils'; | ||
import { ProductResponseItem } from '@woocommerce/types'; | ||
import { useState, useEffect, useCallback, useMemo } from '@wordpress/element'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { | ||
FormTokenField, | ||
// @ts-expect-error Using experimental features | ||
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis | ||
__experimentalToolsPanelItem as ToolsPanelItem, | ||
} from '@wordpress/components'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { ProductCollectionQuery } from '../types'; | ||
|
||
interface HandPickedProductsControlProps { | ||
setQueryAttribute: ( value: Partial< ProductCollectionQuery > ) => void; | ||
selectedProductIds?: string[] | undefined; | ||
} | ||
|
||
/** | ||
* Returns: | ||
* - productsMap: Map of products by id and name. | ||
* - productsList: List of products retrieved. | ||
*/ | ||
function useProducts() { | ||
// Creating a map for fast lookup of products by id or name. | ||
const [ productsMap, setProductsMap ] = useState< | ||
Map< number | string, ProductResponseItem > | ||
>( new Map() ); | ||
|
||
// List of products retrieved | ||
const [ productsList, setProductsList ] = useState< ProductResponseItem[] >( | ||
[] | ||
); | ||
|
||
useEffect( () => { | ||
getProducts( { selected: [] } ).then( ( results ) => { | ||
const newProductsMap = new Map(); | ||
( results as ProductResponseItem[] ).forEach( ( product ) => { | ||
newProductsMap.set( product.id, product ); | ||
newProductsMap.set( product.name, product ); | ||
} ); | ||
|
||
setProductsList( results as ProductResponseItem[] ); | ||
setProductsMap( newProductsMap ); | ||
} ); | ||
}, [] ); | ||
|
||
return { productsMap, productsList }; | ||
} | ||
|
||
const HandPickedProductsControl = ( { | ||
selectedProductIds, | ||
setQueryAttribute, | ||
}: HandPickedProductsControlProps ) => { | ||
const { productsMap, productsList } = useProducts(); | ||
|
||
const onTokenChange = useCallback( | ||
( values: string[] ) => { | ||
// Map the tokens to product ids. | ||
const newHandPickedProductsSet = values.reduce( | ||
( acc, nameOrId ) => { | ||
const product = | ||
productsMap.get( nameOrId ) || | ||
productsMap.get( Number( nameOrId ) ); | ||
if ( product ) acc.add( String( product.id ) ); | ||
return acc; | ||
}, | ||
new Set< string >() | ||
); | ||
|
||
setQueryAttribute( { | ||
woocommerceHandPickedProducts: Array.from( | ||
newHandPickedProductsSet | ||
), | ||
} ); | ||
}, | ||
[ setQueryAttribute, productsMap ] | ||
); | ||
|
||
const suggestions = useMemo( () => { | ||
return ( | ||
productsList | ||
// Filter out products that are already selected. | ||
.filter( | ||
( product ) => | ||
! selectedProductIds?.includes( String( product.id ) ) | ||
) | ||
.map( ( product ) => product.name ) | ||
); | ||
}, [ productsList, selectedProductIds ] ); | ||
|
||
const transformTokenIntoProductName = ( token: string ) => { | ||
const parsedToken = Number( token ); | ||
|
||
if ( Number.isNaN( parsedToken ) ) { | ||
return token; | ||
} | ||
|
||
const product = productsMap.get( parsedToken ); | ||
|
||
return product?.name || ''; | ||
}; | ||
|
||
return ( | ||
<ToolsPanelItem | ||
label={ __( | ||
'Hand-picked Products', | ||
'woo-gutenberg-products-block' | ||
) } | ||
hasValue={ () => !! selectedProductIds?.length } | ||
onDeselect={ () => { | ||
setQueryAttribute( { | ||
woocommerceHandPickedProducts: [], | ||
} ); | ||
} } | ||
> | ||
<FormTokenField | ||
disabled={ ! productsMap.size } | ||
displayTransform={ transformTokenIntoProductName } | ||
label={ __( | ||
'Pick some products', | ||
'woo-gutenberg-products-block' | ||
) } | ||
onChange={ onTokenChange } | ||
suggestions={ suggestions } | ||
// @ts-expect-error Using experimental features | ||
__experimentalValidateInput={ ( value: string ) => | ||
productsMap.has( value ) | ||
} | ||
value={ | ||
! productsMap.size | ||
? [ __( 'Loading…', 'woo-gutenberg-products-block' ) ] | ||
: selectedProductIds || [] | ||
} | ||
/> | ||
</ToolsPanelItem> | ||
); | ||
}; | ||
|
||
export default HandPickedProductsControl; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters