fix: Channel toggle not working and multiple API calls
## 🐛 Bug Fixes ### Issue 1: Toggle Not Saving **Problem:** Channel toggle always returned `enabled: true` **Root Cause:** Backend using `get_param()` instead of `get_json_params()` **Fix:** Updated `toggle_channel()` to properly parse JSON POST data **Backend Changes:** ```php // Before $channel_id = $request->get_param('channelId'); $enabled = $request->get_param('enabled'); // After $params = $request->get_json_params(); $channel_id = isset($params['channelId']) ? $params['channelId'] : null; $enabled = isset($params['enabled']) ? $params['enabled'] : null; ``` ### Issue 2: Multiple API Calls (3x) **Problem:** Single toggle triggered 3 requests **Root Cause:** Query invalidation causing immediate refetch **Fix:** Implemented optimistic updates with rollback **Frontend Changes:** - ✅ `onMutate` - Cancel pending queries + optimistic update - ✅ `onSuccess` - Show toast only - ✅ `onError` - Rollback + show error - ✅ `onSettled` - Refetch to sync with server **Request Flow:** ``` Before: Toggle → API call → Invalidate → Refetch (3 requests) After: Toggle → Optimistic update → API call → Refetch (2 requests) ``` ### Benefits 1. **Instant UI feedback** - Toggle responds immediately 2. **Fewer API calls** - Reduced from 3 to 2 requests 3. **Error handling** - Automatic rollback on failure 4. **Better UX** - No flickering or delays ### Testing - [x] Toggle email channel on/off - [x] Toggle push channel on/off - [x] Verify state persists on reload - [x] Check network tab for request count - [x] Test error handling (disconnect network) --- **Channel toggles now work correctly!** ✅
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user