import {useNavigate, useParams, useSearchParams} from "react-router-dom"; import {useEffect, useState, useRef, useCallback} from "react"; import Navbar from "../components/Navbar.jsx"; import { useAuth } from "../contexts/AuthContext.jsx"; import Comment from "../components/Comment.jsx"; import VideoCard from "../components/VideoCard.jsx"; import Tag from "../components/Tag.jsx"; import {addView, getSimilarVideos, getVideoById, toggleLike} from "../services/video.service.js"; import {subscribe} from "../services/channel.service.js"; import {addComment} from "../services/comment.service.js"; import { getPlaylists } from "../services/user.service.js"; import { addToPlaylist, getPlaylistById } from "../services/playlist.service.js"; import PlaylistVideoCard from "../components/PlaylistVideoCard.jsx"; export default function Video() { const {id} = useParams(); const { user, isAuthenticated } = useAuth(); const videoRef = useRef(null); const controllerRef = useRef(null); const navigation = useNavigate(); const [searchParams] = useSearchParams(); const playlistId = searchParams.get("playlistId"); const isPlaylist = playlistId !== null; const [video, setVideo] = useState(null); const [nextVideo, setNextVideo] = useState(null); const [similarVideos, setSimilarVideos] = useState([]); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [progress, setProgress] = useState(0); const [showControls, setShowControls] = useState(false); const [comment, setComment] = useState(""); const [alerts, setAlerts] = useState([]); const [playlists, setPlaylists] = useState([]); const [isAddToPlaylistOpen, setIsAddToPlaylistOpen] = useState(false); const [currentPlaylist, setCurrentPlaylist] = useState(null); const fetchVideo = useCallback(async () => { // Fetch video data and similar videos based on the video ID from the URL if (!id) { addAlert('error', 'Vidéo introuvable'); navigation('/'); return; } const data = await getVideoById(id, addAlert); if (!data) return; setVideo(data); const similarVideosResponse = await getSimilarVideos(id, addAlert); if (similarVideosResponse) { setSimilarVideos(similarVideosResponse); } // Add views to the video await addView(id, addAlert); }, [id, navigation]); const fetchPlaylists = async () => { const token = localStorage.getItem('token'); if (!token) return; const user = JSON.parse(localStorage.getItem('user')); const data = await getPlaylists(user.id, token, addAlert); if (data) { setPlaylists(data); } } const fetchCurrentPlaylist = async () => { const token = localStorage.getItem('token'); if (!token) return; if (!playlistId) return; setCurrentPlaylist(await getPlaylistById(playlistId, token, addAlert)); } const fetchNextVideo = async () => { const token = localStorage.getItem('token'); if (!token) return; console.log("Fetching next video"); console.log("currentPlaylist", currentPlaylist); console.log("current video id from params:", id, "type:", typeof id); console.log("playlist videos:", currentPlaylist?.videos?.map(v => ({ id: v.id, type: typeof v.id }))); //Find position of current video id in currentPlaylist.videos const currentIndex = currentPlaylist?.videos.findIndex(video => { console.log(`Comparing video.id: ${video.id} (${typeof video.id}) with id: ${id} (${typeof id})`); return video.id.toString() === id.toString(); }); console.log("currentIndex", currentIndex); if (currentIndex !== -1) { if (currentPlaylist?.videos[currentIndex + 1]) { setNextVideo(currentPlaylist.videos[currentIndex + 1]); console.log("nextVideo", currentPlaylist.videos[currentIndex + 1]); } } } const passToNextVideo = () => { if (!nextVideo) { console.log("No next video available"); return; } console.log("Passing to next video:", nextVideo); // Navigate to the next video with playlist context if (playlistId) { navigation(`/video/${nextVideo.id}?playlistId=${playlistId}`); } else { navigation(`/video/${nextVideo.id}`); } } useEffect(() => { fetchVideo(); fetchPlaylists(); fetchCurrentPlaylist(); }, [fetchVideo]); useEffect(() => { fetchNextVideo(); }, [currentPlaylist]); const handlePlayPause = () => { if (videoRef.current) { if (videoRef.current.paused) { videoRef.current.play(); } else { videoRef.current.pause(); } } }; const handleTimeUpdate = () => { if (videoRef.current) { const current = videoRef.current.currentTime; const total = videoRef.current.duration; setCurrentTime(current); setDuration(total); setProgress((current / total) * 100); } }; const handleLoadedMetadata = () => { if (videoRef.current) { setDuration(videoRef.current.duration); } }; const handleTimeBarClick = (event) => { if (videoRef.current) { const timeBar = event.currentTarget; const clickX = event.nativeEvent.offsetX; const totalWidth = timeBar.offsetWidth; const percentage = clickX / totalWidth; const newTime = percentage * duration; videoRef.current.currentTime = newTime; setCurrentTime(newTime); setProgress(percentage * 100); } }; const formatTime = (time) => { if (isNaN(time)) return "0:00"; const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; const formatDate = (dateString) => { if (!dateString) return ""; const months = [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ]; const date = new Date(dateString); const day = date.getDate(); const month = months[date.getMonth()]; const year = date.getFullYear(); return `${day} ${month} ${year}`; }; const handlePlaying = () => { if (videoRef.current) { console.log(`Video is playing at ${videoRef.current.currentTime} seconds`); } } const handleMouseEnter = () => { setShowControls(true); }; const handleMouseLeave = () => { setShowControls(false); }; const handleSubscribe = async () => { if (!isAuthenticated) { navigation('/login'); return; } const response = await subscribe(video.creator.id, addAlert); console.log('Subscription successful:', response); const subscriptionCount = response.subscriptions || 0; setVideo((prevVideo) => { return { ...prevVideo, creator: { ...prevVideo.creator, subscribers: subscriptionCount } }; }) }; const handleLike = async () => { if (!isAuthenticated) { navigation('/login'); return; } // Retrieve the token from localStorage const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } const data = await toggleLike(id, token, addAlert); setVideo((prevVideo) => { return { ...prevVideo, likes: data.likes || prevVideo.likes + 1 // Update likes count }; }) }; const handleComment = async () => { if (!isAuthenticated) { navigation('/login'); return; } if (!comment.trim()) { alert("Comment cannot be empty"); return; } // Retrieve the token from localStorage const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } const data = await addComment(video.id, comment, token, addAlert); setComment(""); // Clear the comment input setVideo((prevVideo) => ({ ...prevVideo, comments: [...(prevVideo.comments || []), data] })); } const addAlert = (type, message) => { const newAlert = { type, message, id: Date.now() }; // Add unique ID setAlerts([...alerts, newAlert]); }; const onCloseAlert = (alertToRemove) => { setAlerts(alerts.filter(alert => alert !== alertToRemove)); }; const handleAddToPlaylist = async (id) => { if (!isAuthenticated) { navigation('/login'); return; } const body = { video: video.id } const token = localStorage.getItem('token'); await addToPlaylist(id, body, token, addAlert); setIsAddToPlaylistOpen(!isAddToPlaylistOpen); } return (
{video ? ( <> {/* Video player section */}
{/* Video controls */}
{/* Time display */}
{formatTime(currentTime)} {formatTime(duration)}
{/* Time bar */}

{video.title}

{/* Channel and like */}
{video.creator?.name

{video.creator?.name}

{video.creator?.subscribers || 0} abonnés

{video.likes}

{/* Video details */}
{/* Tags */} {video.tags && video.tags.length > 0 && (
{video.tags.map((tag, index) => ( ))}
)}

{video.views} vues - {formatDate(video.release_date)}

{video.description}

{/* Comments section */}

Commentaires

{/* Comments list */}
{video.comments && video.comments.length > 0 ? ( video.comments.map((comment, index) => ( )) ) : (

Aucun commentaire pour le moment. Soyez le premier à en publier !

)}
{/* Similar videos section */}
{ !isPlaylist ? (
{similarVideos.map((video, index) => (
))}
) : (

{currentPlaylist?.name}

{ currentPlaylist?.videos && currentPlaylist.videos.length > 0 ? (
{currentPlaylist.videos.map((video, index) => (
))}
) : (

Aucune vidéo trouvée dans cette playlist.

) }
) }
): (

Loading

)}
); }