import { useState, useEffect } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { podcastService, Podcast } from '../services/podcastService'; import { authService } from '../services/authService'; import Header from '../components/Header'; import { BookOpen, Trash2, Loader, Rss } from 'lucide-react'; import { Link } from 'react-router-dom'; export default function Library() { const queryClient = useQueryClient(); const [user, setUser] = useState(null); const [confirmDeleteId, setConfirmDeleteId] = useState(null); useEffect(() => { const loadUser = async () => { try { const response = await authService.getMe(); setUser(response.user); } catch (error) { console.error('Failed to load user:', error); } }; loadUser(); }, []); const { data: subscriptionsData, isLoading } = useQuery({ queryKey: ['podcasts', 'subscriptions'], queryFn: () => podcastService.getUserSubscriptions(), staleTime: 2 * 60 * 1000, }); const unsubscribeMutation = useMutation({ mutationFn: (podcastId: string) => podcastService.unsubscribe(podcastId), 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 || !old.podcasts) return old; // Optimistically filter by subscriptionId or _id as fallback const filtered = old.podcasts.filter((p: any) => String(p.subscriptionId || p._id) !== String(podcastId) ); return { ...old, podcasts: filtered, count: filtered.length }; } ); setConfirmDeleteId(null); }, onSuccess: () => { // Sync the server state after success queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); queryClient.invalidateQueries({ queryKey: ['episodes', 'latest'] }); }, onError: (error: any, podcastId) => { console.error(`[Unsubscribe FAILED] Podcast ID: ${podcastId}`, error); // Rollback: re-fetch the real data from server if the mutation failed queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); const errorMessage = error.response?.data?.message || 'Erreur inconnue'; alert(`Erreur lors du désabonnement (ID: ${podcastId}) : ${errorMessage}`); }, }); const syncMutation = useMutation({ mutationFn: (podcastId: string) => podcastService.syncPodcast(podcastId), onSuccess: (data, podcastId) => { console.log(`[Sync SUCCESS] Podcast ID: ${podcastId}`, data); queryClient.invalidateQueries({ queryKey: ['podcasts', 'subscriptions'] }); queryClient.invalidateQueries({ queryKey: ['episodes', 'latest'] }); }, onError: (error: any, podcastId) => { console.error(`[Sync FAILED] Podcast ID: ${podcastId}`, error); const errorMessage = error.response?.data?.message || 'Erreur de synchronisation'; alert(`Erreur : ${errorMessage}`); }, }); const handleLogout = async () => { try { await authService.logout(); authService.clearTokens(); window.location.href = '/login'; } catch (error) { console.error('Logout failed:', error); } }; const handleUnsubscribeRequest = (id: string) => { console.log("[UI] Demande de désabonnement reçue pour l'ID (Sub/Pod):", id); setConfirmDeleteId(id); }; const handleConfirmUnsubscribe = () => { if (confirmDeleteId) { console.log("[UI] Confirmation du désabonnement pour l'ID:", confirmDeleteId); unsubscribeMutation.mutate(confirmDeleteId); } }; const podcasts: Podcast[] = subscriptionsData?.podcasts ?? []; return (
{/* Title row */}

{isLoading ? 'Chargement...' : `${podcasts.length} abonnement${podcasts.length !== 1 ? 's' : ''}`}

Ajouter un podcast
{/* Content */} {isLoading ? (

Chargement de vos abonnements...

) : podcasts.length === 0 ? (

Votre bibliothèque est vide

Abonnez-vous à des podcasts pour les retrouver ici

Ajouter mon premier podcast
) : (
{podcasts.map((podcast) => (
{/* Podcast cover */} {podcast.imageUrl ? (
{podcast.title}
) : (
)} {/* Info */}

{podcast.title}

{podcast.author && (

{podcast.author}

)} {/* Description preview */} {podcast.description && (

{podcast.description}

)}
{podcast.episodeCount > 0 && ( {podcast.episodeCount} épisodes )} {podcast.language && ( {podcast.language} )}
{/* Last Episode info */} {podcast.lastEpisodeTitle && (

Dernier épisode

{podcast.lastEpisodeTitle}

{podcast.lastEpisodeDate && (

{new Date(podcast.lastEpisodeDate).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' })}

)}
)}
{/* Unsubscribe button */} {confirmDeleteId === (podcast.subscriptionId || podcast._id) ? (
Confirmer le désabonnement ?
) : (
{podcast.episodeCount === 0 && (

{syncMutation.isPending && syncMutation.variables === (podcast.subscriptionId || podcast._id) ? ( ) : ( )} Aucun épisode trouvé

)}
)}
))}
)}
); }