Commit 46af826b778 for woocommerce

commit 46af826b7783246fb6148f6166837ae0651f395f
Author: Seghir Nadir <nadir.seghir@gmail.com>
Date:   Thu Jul 9 14:55:41 2026 +0100

    Fix Local Pickup settings save confirmation notice (#66459)

    The success notice was gated on the API response deep-equaling the sent
    payload. The controller sanitizes input (wp_kses_post/sanitize_text_field)
    before echoing it back, so values like "Ring bell & wait" come back as
    "Ring bell &amp; wait" and the notice never fired despite a successful,
    persisted save. Gate the notice on request success instead, and surface an
    error notice on failure.

diff --git a/plugins/woocommerce/changelog/66404-fix-local-pickup-save-notice b/plugins/woocommerce/changelog/66404-fix-local-pickup-save-notice
new file mode 100644
index 00000000000..e1bf21b6525
--- /dev/null
+++ b/plugins/woocommerce/changelog/66404-fix-local-pickup-save-notice
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Show the Local Pickup settings save confirmation on a successful save (and an error notice on failure), instead of only when the server response matched the sent payload, which suppressed the notice when values were sanitized (e.g. "&" normalized to "&amp;").
diff --git a/plugins/woocommerce/client/blocks/assets/js/extensions/shipping-methods/pickup-location/settings-context.tsx b/plugins/woocommerce/client/blocks/assets/js/extensions/shipping-methods/pickup-location/settings-context.tsx
index a90aa308e8c..7b3d83c273b 100644
--- a/plugins/woocommerce/client/blocks/assets/js/extensions/shipping-methods/pickup-location/settings-context.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/extensions/shipping-methods/pickup-location/settings-context.tsx
@@ -12,7 +12,6 @@ import type { UniqueIdentifier } from '@dnd-kit/core';
 import apiFetch from '@wordpress/api-fetch';
 import { dispatch } from '@wordpress/data';
 import { __ } from '@wordpress/i18n';
-import fastDeepEqual from 'fast-deep-equal/es6';
 import { store as noticesStore } from '@wordpress/notices';

 /**
@@ -145,32 +144,37 @@ export const SettingsProvider = ( {
 		setIsSaving( true );
 		setIsDirty( false );

-		// @todo This should be improved to include error handling in case of API failure, or invalid data being sent that
-		// does not match the schema. This would fail silently on the API side.
+		// A resolved apiFetch means the request succeeded (2xx); the server
+		// sanitizes the payload before echoing it back, so the response will not
+		// necessarily match what we sent. Gate the notice on success, not on the
+		// response matching the payload, otherwise sanitized values (e.g. "&"
+		// normalized to "&amp;") would suppress the confirmation on a save that
+		// actually persisted.
 		apiFetch( {
 			path: '/wc/v3/pickup-locations',
 			method: 'POST',
 			data,
-		} ).then( ( response ) => {
-			setIsSaving( false );
-			if (
-				fastDeepEqual(
-					response.pickup_location_settings,
-					data.pickup_location_settings
-				) &&
-				fastDeepEqual(
-					response.pickup_locations,
-					data.pickup_locations
-				)
-			) {
+		} )
+			.then( () => {
 				dispatch( noticesStore ).createSuccessNotice(
 					__(
 						'Local Pickup settings have been saved.',
 						'woocommerce'
 					)
 				);
-			}
-		} );
+			} )
+			.catch( () => {
+				setIsDirty( true );
+				dispatch( noticesStore ).createErrorNotice(
+					__(
+						'There was an error saving your Local Pickup settings. Please try again.',
+						'woocommerce'
+					)
+				);
+			} )
+			.finally( () => {
+				setIsSaving( false );
+			} );
 	}, [ settings, pickupLocations ] );

 	const settingsData = {