From f50d1072a9e05ed6adaa423ed9ed271afdb241a9 Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Thu, 16 Apr 2026 13:00:10 +0200 Subject: [PATCH] feat: add Library page to manage and unsubscribe from podcast subscriptions --- frontend/src/pages/Library.tsx | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/frontend/src/pages/Library.tsx b/frontend/src/pages/Library.tsx index 226703b..9a1e549 100644 --- a/frontend/src/pages/Library.tsx +++ b/frontend/src/pages/Library.tsx @@ -31,15 +31,31 @@ export default function Library() { const unsubscribeMutation = useMutation({ mutationFn: (podcastId: string) => podcastService.unsubscribe(podcastId), - onSuccess: () => { - // Invalidate subscriptions and latest episodes so dashboard refreshes too - queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); - queryClient.invalidateQueries({ queryKey: ['episodes', 'latest'] }); + onMutate: async (podcastId: string) => { + // Cancel outgoing refetches to avoid overwriting our optimistic update + await queryClient.cancelQueries({ queryKey: ['podcasts', 'subscriptions'] }); + + // Optimistic update: remove the podcast from the local cache immediately + queryClient.setQueryData( + ['podcasts', 'subscriptions'], + (old: any) => { + if (!old) return old; + const filtered = old.podcasts.filter((p: any) => p._id !== podcastId); + return { podcasts: filtered, count: filtered.length }; + } + ); + setConfirmDeleteId(null); }, - onError: (error: any) => { + onSuccess: () => { + // Sync the server state after success + queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); + queryClient.invalidateQueries({ queryKey: ['episodes', 'latest'] }); + }, + onError: (error: any, podcastId, context) => { + // Rollback: re-fetch the real data from server if the mutation failed + queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); alert(`Erreur : ${error.response?.data?.message || 'Impossible de se désabonner'}`); - setConfirmDeleteId(null); }, });