diff --git a/packages/js/product-editor/changelog/update-product-editor-handle-shipping-classes-slug b/packages/js/product-editor/changelog/update-product-editor-handle-shipping-classes-slug new file mode 100644 index 00000000000..e643e4fd648 --- /dev/null +++ b/packages/js/product-editor/changelog/update-product-editor-handle-shipping-classes-slug @@ -0,0 +1,4 @@ +Significance: patch +Type: add + +Product Block Editor: populate shipping class slug automatically diff --git a/packages/js/product-editor/src/components/add-new-shipping-class-modal/add-new-shipping-class-modal.tsx b/packages/js/product-editor/src/components/add-new-shipping-class-modal/add-new-shipping-class-modal.tsx index caac352bf60..98ab1a788c3 100644 --- a/packages/js/product-editor/src/components/add-new-shipping-class-modal/add-new-shipping-class-modal.tsx +++ b/packages/js/product-editor/src/components/add-new-shipping-class-modal/add-new-shipping-class-modal.tsx @@ -1,7 +1,6 @@ /** * External dependencies */ -import { Button, Modal, TextControl } from '@wordpress/components'; import { useState, createElement, @@ -10,6 +9,19 @@ import { import { __ } from '@wordpress/i18n'; import { Form, FormErrors, useFormContext } from '@woocommerce/components'; import { ProductShippingClass } from '@woocommerce/data'; +import { addQueryArgs } from '@wordpress/url'; +import apiFetch from '@wordpress/api-fetch'; +import { + Button, + Modal, + TextControl, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore We need this to import the block modules for registration. + __experimentalInputControl as InputControl, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore We need this to import the block modules for registration. + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, +} from '@wordpress/components'; export type ShippingClassFormProps = { onAdd: () => Promise< ProductShippingClass >; @@ -33,6 +45,58 @@ function ShippingClassForm( { onAdd, onCancel }: ShippingClassFormProps ) { } ); } + // State to control the automatic slug generation. + const [ isRequestingSlug, setIsRequestingSlug ] = useState( false ); + + // Get the shipping class name value. + const shippingNameInputValue = String( getInputProps( 'name' ).value ); + + const [ prevNameValue, setPrevNameValue ] = useState( + shippingNameInputValue + ); + + /** + * Pull the slug suggestion from the server, + * and update the slug input field. + */ + async function pullAndUpdateSlugInputField() { + setIsRequestingSlug( true ); + + // Avoid making the request if the name has not changed. + if ( prevNameValue === shippingNameInputValue ) { + return; + } + + setPrevNameValue( shippingNameInputValue ); + + const url = `/wc/v3/products/shipping_classes/slug-suggestion`; + const slug: string = await apiFetch( { + path: addQueryArgs( url, { name: shippingNameInputValue } ), + method: 'GET', + } ); + + setIsRequestingSlug( false ); + + getInputProps( 'slug' ).onChange( slug ); + } + + const isGenerateButtonDisabled = + isRequestingSlug || + ! shippingNameInputValue?.length || + prevNameValue === shippingNameInputValue; + + /** + * Get a slug suggestion based on the shipping class name. + * This function is called when the name field is blurred. + */ + function getSlugSuggestion() { + if ( ! isRequestingSlug ) { + return; + } + + pullAndUpdateSlugInputField(); + } + return (