import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { getComments, createComment } from '../services/commentService'; import { useUser } from '@/features/auth/hooks/useUser'; import { useToast } from '@/hooks/useToast'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { MessageCircle, Send, Loader2 } from 'lucide-react'; import { LoadingSpinner } from '@/components/ui/loading-spinner'; import { CommentThread } from './CommentThread'; import type { TrackComment } from '../services/commentService'; import { ErrorDisplay } from '@/components/ui/ErrorDisplay'; // FE-PAGE-007: Complete Track Detail page implementation - Comments Section interface CommentSectionProps { trackId: string; } export function CommentSection({ trackId }: CommentSectionProps) { const { data: user } = useUser(); const toast = useToast(); const queryClient = useQueryClient(); const [newComment, setNewComment] = useState(''); const [mutationError, setMutationError] = useState(null); const [page, setPage] = useState(1); const limit = 20; const { data: commentsData, isLoading, error, } = useQuery({ queryKey: ['trackComments', trackId, page], queryFn: () => getComments(trackId, page, limit), enabled: !!trackId, }); // Action 3.4.1.3: Store last comment content for retry const [lastCommentContent, setLastCommentContent] = useState(''); const [retryCount, setRetryCount] = useState(0); const createCommentMutation = useMutation({ mutationFn: (content: string) => createComment(trackId, content), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['trackComments', trackId] }); setNewComment(''); setMutationError(null); setRetryCount(0); setLastCommentContent(''); toast.success('Commentaire publié'); }, onError: (error: any) => { setMutationError( new Error(error.message || 'Erreur lors de la publication'), ); // Store content for retry setLastCommentContent(newComment.trim()); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!newComment.trim() || !user) return; setLastCommentContent(newComment.trim()); createCommentMutation.mutate(newComment.trim()); }; // Action 3.4.1.3: Retry handler for failed mutations const handleRetry = async () => { if (!lastCommentContent || retryCount >= 3) return; setRetryCount((prev) => prev + 1); try { await createCommentMutation.mutateAsync(lastCommentContent); } catch (error) { // Error will be handled by mutation's onError } }; // Filter to show only top-level comments (no parent_id) const topLevelComments = commentsData?.comments?.filter((c: TrackComment) => !c.parent_id) || []; const total = commentsData?.total || 0; const totalPages = Math.ceil(total / limit); return ( Commentaires ({commentsData?.total || 0}) {mutationError && ( { setMutationError(null); setRetryCount(0); setLastCommentContent(''); }} /> )} {/* Comment Form */} {user ? (
setNewComment(e.target.value)} placeholder="Écrire un commentaire..." maxLength={500} />
) : (

Connectez-vous pour commenter

)} {/* Comments List */} {isLoading ? (
) : error ? ( queryClient.invalidateQueries({ queryKey: ['trackComments', trackId], }) } /> ) : topLevelComments.length === 0 ? (
Aucun commentaire pour le moment. Soyez le premier à commenter !
) : (
{topLevelComments.map((comment: TrackComment) => ( ))} {/* Pagination */} {totalPages > 1 && (
Page {page} sur {totalPages}
)}
)}
); }