Add reorder grouped products option (#42766)

* Add re-order modal

* Consolidate some of the styling and components

* Add changelog

* Only show reorder when products are added, and remove 'x' from reorder modal
This commit is contained in:
louwie17 2023-12-14 16:01:55 -04:00 committed by GitHub
parent 3042b9fba6
commit b406a084e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 168 additions and 27 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update products list field to add re-order option.

View File

@ -24,6 +24,7 @@ import classNames from 'classnames';
import {
AddProductsModal,
getProductImageStyle,
ReorderProductsModal,
} from '../../../components/add-products-modal';
import { ProductEditorBlockEditProps } from '../../../types';
import { Shirt, Pants, Glasses } from './images';
@ -40,6 +41,8 @@ export function Edit( {
const { property } = attributes;
const blockProps = useWooBlockProps( attributes );
const [ openAddProductsModal, setOpenAddProductsModal ] = useState( false );
const [ openReorderProductsModal, setOpenReorderProductsModal ] =
useState( false );
const [ isLoading, setIsLoading ] = useState( false );
const [ preventFetch, setPreventFetch ] = useState( false );
const [ groupedProductIds, setGroupedProductIds ] = useEntityProp<
@ -72,6 +75,10 @@ export function Edit( {
setOpenAddProductsModal( true );
}
function handleReorderProductsButtonClick() {
setOpenReorderProductsModal( true );
}
function handleAddProductsModalSubmit( value: Product[] ) {
const newGroupedProducts = [ ...groupedProducts, ...value ];
setPreventFetch( true );
@ -82,10 +89,20 @@ export function Edit( {
setOpenAddProductsModal( false );
}
function handleReorderProductsModalSubmit( value: Product[] ) {
setGroupedProducts( value );
setGroupedProductIds( value.map( ( product ) => product.id ) );
setOpenReorderProductsModal( false );
}
function handleAddProductsModalClose() {
setOpenAddProductsModal( false );
}
function handleReorderProductsModalClose() {
setOpenReorderProductsModal( false );
}
function removeProductHandler( product: Product ) {
return function handleRemoveClick() {
const newGroupedProducts = groupedProducts.filter(
@ -104,6 +121,14 @@ export function Edit( {
return (
<div { ...blockProps }>
<div className="wp-block-woocommerce-product-list-field__header">
{ ! isLoading && groupedProducts.length > 0 && (
<Button
onClick={ handleReorderProductsButtonClick }
variant="tertiary"
>
{ __( 'Reorder', 'woocommerce' ) }
</Button>
) }
<Button
onClick={ handleAddProductsButtonClick }
variant="secondary"
@ -294,6 +319,13 @@ export function Edit( {
onClose={ handleAddProductsModalClose }
/>
) }
{ openReorderProductsModal && (
<ReorderProductsModal
products={ groupedProducts }
onSubmit={ handleReorderProductsModalSubmit }
onClose={ handleReorderProductsModalClose }
/>
) }
</div>
);
}

View File

@ -7,6 +7,7 @@
display: flex;
align-items: center;
justify-content: end;
gap: $gap-smaller;
}
&__empty-state {

View File

@ -12,7 +12,7 @@ import {
useState,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { closeSmall, dragHandle } from '@wordpress/icons';
import { closeSmall } from '@wordpress/icons';
import {
__experimentalSelectControl as SelectControl,
__experimentalSelectControlMenu as Menu,
@ -21,13 +21,11 @@ import {
} from '@woocommerce/components';
import { CurrencyContext } from '@woocommerce/currency';
import { PRODUCTS_STORE_NAME, Product } from '@woocommerce/data';
import classNames from 'classnames';
/**
* Internal dependencies
*/
import { AddProductsModalProps } from './types';
import { useDraggable } from '../../hooks/use-draggable';
export function getProductImageStyle( product: Product ) {
return product.images.length > 0
@ -103,10 +101,6 @@ export function AddProductsModal( {
};
}
const { container, draggable, handler } = useDraggable( {
onSort: setSelectedProducts,
} );
return (
<Modal
title={ __( 'Add products to this group', 'woocommerce' ) }
@ -204,29 +198,12 @@ export function AddProductsModal( {
</div>
{ Boolean( selectedProducts.length ) && (
<ul
{ ...container }
className={ classNames(
'woocommerce-add-products-modal__list',
container.className
) }
>
<ul className="woocommerce-add-products-modal__list">
{ selectedProducts.map( ( item ) => (
<li
{ ...draggable }
key={ item.id }
className="woocommerce-add-products-modal__list-item"
>
<Button
{ ...handler }
icon={ dragHandle }
variant="tertiary"
type="button"
aria-label={ __(
'Sortable handler',
'woocommerce'
) }
/>
<div
className="woocommerce-add-products-modal__list-item-image"
style={ getProductImageStyle( item ) }

View File

@ -1,2 +1,3 @@
export * from './add-products-modal';
export * from './reorder-products-modal';
export * from './types';

View File

@ -0,0 +1,119 @@
/**
* External dependencies
*/
import { FormEvent } from 'react';
import { Button, Modal } from '@wordpress/components';
import { createElement, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { dragHandle } from '@wordpress/icons';
import { Product } from '@woocommerce/data';
import classNames from 'classnames';
/**
* Internal dependencies
*/
import { ReorderProductsModalProps } from './types';
import { useDraggable } from '../../hooks/use-draggable';
import { getProductImageStyle } from './add-products-modal';
export function ReorderProductsModal( {
products,
onSubmit,
onClose,
}: ReorderProductsModalProps ) {
const [ selectedProducts, setSelectedProducts ] = useState< Product[] >( [
...products,
] );
function handleSubmit( event: FormEvent< HTMLFormElement > ) {
event.preventDefault();
onSubmit( [ ...selectedProducts ] );
}
function handleCancelClick() {
onClose();
}
const { container, draggable, handler } = useDraggable( {
onSort: setSelectedProducts,
} );
return (
<Modal
title={ __( 'Reorder products in this group', 'woocommerce' ) }
className="woocommerce-reorder-products-modal"
onRequestClose={ onClose }
>
<form
noValidate
onSubmit={ handleSubmit }
className="woocommerce-add-products-modal__form"
>
<fieldset className="woocommerce-add-products-modal__form-group">
<legend className="woocommerce-add-products-modal__form-group-title">
{ __(
'Click and drag to reorder on the product page.',
'woocommerce'
) }
</legend>
{ Boolean( selectedProducts.length ) && (
<ul
{ ...container }
className={ classNames(
'woocommerce-add-products-modal__list',
container.className
) }
>
{ selectedProducts.map( ( item ) => (
<li
{ ...draggable }
key={ item.id }
className="woocommerce-add-products-modal__list-item"
>
<Button
{ ...handler }
icon={ dragHandle }
variant="tertiary"
type="button"
aria-label={ __(
'Sortable handler',
'woocommerce'
) }
/>
<div
className="woocommerce-add-products-modal__list-item-image"
style={ getProductImageStyle( item ) }
/>
<div className="woocommerce-add-products-modal__list-item-content">
<div className="woocommerce-add-products-modal__list-item-title">
{ item.name }
</div>
<div className="woocommerce-add-products-modal__list-item-description">
{ item.sku }
</div>
</div>
</li>
) ) }
</ul>
) }
</fieldset>
<div className="woocommerce-add-products-modal__actions">
<Button
variant="tertiary"
type="button"
onClick={ handleCancelClick }
>
{ __( 'Cancel', 'woocommerce' ) }
</Button>
<Button variant="primary" type="submit">
{ __( 'Done', 'woocommerce' ) }
</Button>
</div>
</form>
</Modal>
);
}

View File

@ -1,4 +1,5 @@
.woocommerce-add-products-modal {
.woocommerce-add-products-modal,
.woocommerce-reorder-products-modal {
@include breakpoint(">600px") {
width: calc(100% - 32px);
}

View File

@ -1,10 +1,16 @@
/**
* External dependencies
*/
import { Product } from '@woocommerce/data';
import type { Product } from '@woocommerce/data';
export type AddProductsModalProps = {
initialValue: Product[];
onSubmit( value: Product[] ): void;
onClose(): void;
};
export type ReorderProductsModalProps = {
products: Product[];
onSubmit( value: Product[] ): void;
onClose(): void;
};