diff --git a/packages/js/product-editor/changelog/add-39688 b/packages/js/product-editor/changelog/add-39688 new file mode 100644 index 00000000000..67da99dbb8c --- /dev/null +++ b/packages/js/product-editor/changelog/add-39688 @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Show a summary when adding or removing variation option values diff --git a/packages/js/product-editor/src/components/attribute-control/attribute-control.tsx b/packages/js/product-editor/src/components/attribute-control/attribute-control.tsx index 6c890b3a703..5154cb37f5d 100644 --- a/packages/js/product-editor/src/components/attribute-control/attribute-control.tsx +++ b/packages/js/product-editor/src/components/attribute-control/attribute-control.tsx @@ -354,6 +354,7 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( { handleEdit( updatedAttribute ); } } attribute={ currentAttribute } + attributes={ value } /> ) } { removingAttribute && ( diff --git a/packages/js/product-editor/src/components/attribute-control/edit-attribute-modal.tsx b/packages/js/product-editor/src/components/attribute-control/edit-attribute-modal.tsx index 27f4d8f2c64..c8ae9390b57 100644 --- a/packages/js/product-editor/src/components/attribute-control/edit-attribute-modal.tsx +++ b/packages/js/product-editor/src/components/attribute-control/edit-attribute-modal.tsx @@ -1,14 +1,14 @@ /** * External dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { Button, Modal, CheckboxControl, TextControl, } from '@wordpress/components'; -import { useState, createElement, Fragment } from '@wordpress/element'; +import { useState, createElement, Fragment, useMemo } from '@wordpress/element'; import { __experimentalTooltip as Tooltip, __experimentalSelectControlMenuSlot as SelectControlMenuSlot, @@ -22,6 +22,8 @@ import { CustomAttributeTermInputField, } from '../attribute-term-input-field'; import { EnhancedProductAttribute } from '../../hooks/use-product-attributes'; +import { Notice } from '../notice'; +import { getAttributeId } from './utils'; type EditAttributeModalProps = { title?: string; @@ -43,6 +45,7 @@ type EditAttributeModalProps = { onCancel: () => void; onEdit: ( alteredAttribute: EnhancedProductAttribute ) => void; attribute: EnhancedProductAttribute; + attributes: EnhancedProductAttribute[]; }; export const EditAttributeModal: React.FC< EditAttributeModalProps > = ( { @@ -77,6 +80,7 @@ export const EditAttributeModal: React.FC< EditAttributeModalProps > = ( { onCancel, onEdit, attribute, + attributes, } ) => { const [ editableAttribute, setEditableAttribute ] = useState< EnhancedProductAttribute | undefined @@ -84,6 +88,71 @@ export const EditAttributeModal: React.FC< EditAttributeModalProps > = ( { const isCustomAttribute = editableAttribute?.id === 0; + const { additions, deletions } = useMemo( () => { + if ( ! attribute.variation ) { + return {}; + } + + const variationsSubTotal = attributes + .filter( + ( otherAttribute ) => + getAttributeId( otherAttribute ) !== + getAttributeId( attribute ) + ) + .reduce( + ( subTotal, { terms } ) => subTotal * ( terms?.length ?? 1 ), + 1 + ); + + const currentAttributeTermsCount = attribute.terms?.length ?? 0; + const variationsTotal = variationsSubTotal * currentAttributeTermsCount; + + const addedTermsCount = + editableAttribute?.terms?.filter( + ( editedTerm ) => + ! attribute.terms?.some( + ( currentTerm ) => currentTerm.id === editedTerm.id + ) + )?.length ?? 0; + const addedTermsTotal = + currentAttributeTermsCount + addedTermsCount || 1; + + const remainedTermsCount = + attribute.terms?.filter( ( currentTerm ) => + editableAttribute?.terms?.some( + ( editedTerm ) => currentTerm.id === editedTerm.id + ) + )?.length ?? 0; + + return { + additions: Math.abs( + variationsTotal - variationsSubTotal * addedTermsTotal + ), + deletions: Math.abs( + variationsTotal - variationsSubTotal * remainedTermsCount + ), + }; + }, [ attributes, attribute, editableAttribute ] ); + + function getNoticeMessage() { + const additionsMessage = sprintf( + // translators: %d is the amount of variations to be added + __( '%d variations will be added', 'woocommerce' ), + additions + ); + const deletionsMessage = sprintf( + // translators: %d is the amount of variations to be removed + __( '%d variations will be removed', 'woocommerce' ), + deletions + ); + if ( additions && deletions ) { + return sprintf( '%s, %s.', additionsMessage, deletionsMessage ); + } else if ( additions ) { + return sprintf( '%s.', additionsMessage ); + } + return sprintf( '%s.', deletionsMessage ); + } + return ( <> = ( { ) } + + { Boolean( additions || deletions ) && ( + { getNoticeMessage() } + ) }