diff --git a/admin-spa/src/routes/Settings/Notifications/Channels.tsx b/admin-spa/src/routes/Settings/Notifications/Channels.tsx index fe19d97..6165b94 100644 --- a/admin-spa/src/routes/Settings/Notifications/Channels.tsx +++ b/admin-spa/src/routes/Settings/Notifications/Channels.tsx @@ -49,13 +49,37 @@ export default function NotificationChannels() { mutationFn: async ({ channelId, enabled }: { channelId: string; enabled: boolean }) => { return api.post('/notifications/channels/toggle', { channelId, enabled }); }, + onMutate: async ({ channelId, enabled }) => { + // Cancel outgoing refetches + await queryClient.cancelQueries({ queryKey: ['notification-channels'] }); + + // Snapshot previous value + const previousChannels = queryClient.getQueryData(['notification-channels']); + + // Optimistically update + queryClient.setQueryData(['notification-channels'], (old: any) => { + if (!old) return old; + return old.map((channel: any) => + channel.id === channelId ? { ...channel, enabled } : channel + ); + }); + + return { previousChannels }; + }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['notification-channels'] }); toast.success(__('Channel updated')); }, - onError: (error: any) => { + onError: (error: any, variables, context: any) => { + // Rollback on error + if (context?.previousChannels) { + queryClient.setQueryData(['notification-channels'], context.previousChannels); + } toast.error(error?.message || __('Failed to update channel')); }, + onSettled: () => { + // Refetch after mutation + queryClient.invalidateQueries({ queryKey: ['notification-channels'] }); + }, }); // Check push notification support diff --git a/includes/Api/NotificationsController.php b/includes/Api/NotificationsController.php index 3b15618..2727410 100644 --- a/includes/Api/NotificationsController.php +++ b/includes/Api/NotificationsController.php @@ -553,8 +553,9 @@ class NotificationsController { * @return WP_REST_Response */ public function toggle_channel(WP_REST_Request $request) { - $channel_id = $request->get_param('channelId'); - $enabled = $request->get_param('enabled'); + $params = $request->get_json_params(); + $channel_id = isset($params['channelId']) ? $params['channelId'] : null; + $enabled = isset($params['enabled']) ? $params['enabled'] : null; if (empty($channel_id)) { return new WP_Error( @@ -564,6 +565,14 @@ class NotificationsController { ); } + if ($enabled === null) { + return new WP_Error( + 'invalid_enabled', + __('Enabled parameter is required', 'woonoow'), + ['status' => 400] + ); + } + // Only allow toggling built-in channels if ($channel_id === 'email') { update_option('woonoow_email_notifications_enabled', (bool) $enabled);