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?.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
)}
);
}