From e06f342c8ee70dab12ecb82982a24f58f2497321 Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Tue, 21 Apr 2026 10:06:09 +0200 Subject: [PATCH] fix: lu badge persistence + remove ? + fix duplicate buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EpisodeCard: change 'Lu ?' → 'Marquer' so the toggle button no longer shows a confusing question mark next to completed episodes - Dashboard: fix episodes reappearing in 'Continuer l'écoute' after navigation. handleToggleRead now does an optimistic update on BOTH local state AND all TanStack Query cache pages (setQueriesData), so the 'lu' state survives page navigation without a server roundtrip. On error, cache is invalidated to revert to server truth. - Dashboard: 'Découvrir' button now links to /add (discover new podcasts) instead of /trending — was identical to 'Parcourir les tendances' button Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/EpisodeCard.tsx | 2 +- frontend/src/pages/Dashboard.tsx | 39 +++++++++++++++---------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/EpisodeCard.tsx b/frontend/src/components/EpisodeCard.tsx index 6ce6655..b805a2e 100644 --- a/frontend/src/components/EpisodeCard.tsx +++ b/frontend/src/components/EpisodeCard.tsx @@ -139,7 +139,7 @@ export default function EpisodeCard({ episode, onPlay, onDetails, onToggleRead } ? : } - {isCompleted ? 'Lu' : 'Lu ?'} + {isCompleted ? 'Lu' : 'Marquer'} )} diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 1853ef4..e232be9 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { useQuery } from '@tanstack/react-query'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; import { Link } from 'react-router-dom'; import { episodeService, Episode } from '../services/episodeService'; import { authService } from '../services/authService'; @@ -13,6 +13,7 @@ import { Sparkles, Play, Clock, TrendingUp, Loader, RefreshCcw } from 'lucide-re export default function Dashboard() { const { playEpisode, currentEpisode, closePlayer, setUserId } = useAudio(); + const queryClient = useQueryClient(); const [user, setUser] = useState(null); const [detailsEpisode, setDetailsEpisode] = useState(null); const [isDetailsOpen, setIsDetailsOpen] = useState(false); @@ -41,21 +42,29 @@ export default function Dashboard() { }; const handleToggleRead = async (episode: Episode, completed: boolean) => { + const newProgress = { position: completed ? episode.duration : 0, isCompleted: completed }; + // Optimistic update: local state + all cached query pages + setEpisodes(prev => + prev.map(ep => ep._id === episode._id ? { ...ep, progress: newProgress } : ep) + ); + queryClient.setQueriesData( + { queryKey: ['episodes', 'latest'], exact: false }, + (old: any) => { + if (!old?.episodes) return old; + return { + ...old, + episodes: old.episodes.map((ep: Episode) => + ep._id === episode._id ? { ...ep, progress: newProgress } : ep + ), + }; + } + ); try { - await episodeService.saveProgress( - episode._id, - completed ? episode.duration : 0, - completed - ); - setEpisodes(prev => - prev.map(ep => - ep._id === episode._id - ? { ...ep, progress: { position: completed ? ep.duration : 0, isCompleted: completed } } - : ep - ) - ); + await episodeService.saveProgress(episode._id, newProgress.position, completed); } catch (error) { console.error('Failed to toggle read state:', error); + // Revert on error + queryClient.invalidateQueries({ queryKey: ['episodes', 'latest'] }); } }; @@ -181,9 +190,9 @@ export default function Dashboard() { Reprendre : {episodesInProgress[0].title.substring(0, 20)}... ) : ( - + - Découvrir + Découvrir des podcasts )}