import {useNavigate, useParams} 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"; export default function Video() { // This component can be used to display a video player or video-related content. const {id} = useParams(); const { user, isAuthenticated } = useAuth(); const videoRef = useRef(null); const controllerRef = useRef(null); const navigation = useNavigate(); const [video, setVideo] = 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 fetchVideo = useCallback(async () => { // Fetch video data and similar videos based on the video ID from the URL try { const response = await fetch(`/api/videos/${id}`); if (!response.ok) { throw new Error('Network response was not ok'); } const videoData = await response.json(); setVideo(videoData); } catch (error) { addAlert('error', 'Erreur lors de la récupération de la vidéo'); } try { const response = await fetch(`/api/videos/${id}/similar`); if (!response.ok) { throw new Error('Network response was not ok'); } const similarVideosData = await response.json(); setSimilarVideos(similarVideosData); } catch (error) { addAlert('error', 'Erreur lors de la récupération des vidéos similaires'); } // Add views to the video try { const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } await fetch(`/api/videos/${id}/views`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); } catch (error) { addAlert('error', 'Erreur lors de l\'ajout des vues à la vidéo'); } }, [id, navigation]); const fetchComments = useCallback(async () => { // Fetch comments for the video try { const response = await fetch(`/api/comments/video/${id}`); if (!response.ok) { throw new Error('Network response was not ok'); } const commentsData = await response.json(); setVideo((prevVideo) => ({ ...prevVideo, comments: commentsData })); } catch (error) { addAlert('error', 'Erreur lors de la récupération des commentaires'); } }, [id]); useEffect(() => { fetchVideo(); }, [fetchVideo]); 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; } try { // Retrieve the token from localStorage const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } const response = await fetch(`/api/channels/${video.creator.id}/subscribe`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ userId: user.id }) }); if (!response.ok) { throw new Error('Failed to subscribe'); } const data = await response.json(); console.log('Subscription successful:', data); const subscriptionCount = data.subscriptions || 0; setVideo((prevVideo) => { return { ...prevVideo, creator: { ...prevVideo.creator, subscribers: subscriptionCount } }; }) } catch (error) { addAlert('error', 'Erreur lors de l\'abonnement'); } }; const handleLike = async () => { if (!isAuthenticated) { navigation('/login'); return; } try { // Retrieve the token from localStorage const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } const response = await fetch(`/api/videos/${id}/like`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); if (!response.ok) { throw new Error('Failed to like video'); } const data = await response.json(); setVideo((prevVideo) => { return { ...prevVideo, likes: data.likes || prevVideo.likes + 1 // Update likes count }; }) } catch (error) { addAlert('error', 'Erreur lors de l\'ajout du like'); } }; const handleComment = async () => { if (!isAuthenticated) { navigation('/login'); return; } if (!comment.trim()) { alert("Comment cannot be empty"); return; } try { // Retrieve the token from localStorage const token = localStorage.getItem('token'); if (!token) { navigation('/login'); return; } const response = await fetch(`/api/comments/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ content: comment, video: id }) }); if (!response.ok) { throw new Error('Failed to post comment'); } const data = await response.json(); console.log('Comment posted successfully:', data); setComment(""); // Clear the comment input setVideo((prevVideo) => ({ ...prevVideo, comments: [...(prevVideo.comments || []), data] // Add the new comment to the existing comments })); } catch (error) { addAlert('error', 'Erreur lors de la publication du commentaire'); } } 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)); }; 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 */}
{similarVideos.map((video, index) => (
))}
): (

Loading

)}
); }