You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
9.4 KiB
222 lines
9.4 KiB
import Navbar from "../components/Navbar.jsx";
|
|
import {useEffect, useState} from "react";
|
|
import {useNavigate, useParams} from "react-router-dom";
|
|
import {useAuth} from "../contexts/AuthContext.jsx";
|
|
import VideoStatListElement from "../components/VideoStatListElement.jsx";
|
|
|
|
|
|
export default function ManageChannel() {
|
|
|
|
const {id} = useParams();
|
|
const {user} = useAuth();
|
|
const navigate = useNavigate();
|
|
|
|
const [channel, setChannel] = useState();
|
|
const [channelStats, setChannelStats] = useState();
|
|
const [channelName, setChannelName] = useState(null);
|
|
const [description, setDescription] = useState(null);
|
|
const [editMode, setEditMode] = useState(false);
|
|
const [alerts, setAlerts] = useState([]);
|
|
|
|
const token = localStorage.getItem("token");
|
|
const nonEditModeClasses = "text-2xl font-bold text-white p-2 focus:text-white focus:outline-none w-full font-montserrat resizable-none text-center";
|
|
const editModeClasses = nonEditModeClasses + " glassmorphism";
|
|
|
|
const nonEditModeClassesTextArea = "text-md font-normal text-white p-2 focus:text-white focus:outline-none w-full font-montserrat resizable-none w-full"
|
|
const editModeClassesTextArea = nonEditModeClassesTextArea + " glassmorphism h-48";
|
|
|
|
useEffect(() => {
|
|
fetchChannelData()
|
|
fetchChannelStats()
|
|
}, []);
|
|
|
|
const fetchChannelData = async () => {
|
|
try {
|
|
const request = await fetch(`/api/channels/${id}`, {
|
|
method: "GET",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`
|
|
}
|
|
})
|
|
const result = await request.json();
|
|
setChannel(result);
|
|
|
|
} catch (error) {
|
|
console.error("Error fetching channel data:", error);
|
|
}
|
|
|
|
}
|
|
const fetchChannelStats = async () => {
|
|
try {
|
|
const request = await fetch(`/api/channels/${id}/stats`, {
|
|
method: "GET",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`
|
|
}
|
|
})
|
|
const result = await request.json();
|
|
setChannelStats(result);
|
|
} catch (error) {
|
|
console.error("Error fetching channel stats", error);
|
|
}
|
|
}
|
|
|
|
const handleUpdateChannel = async () => {
|
|
if (!editMode) return;
|
|
|
|
try {
|
|
const response = await fetch(`/api/channels/${id}`, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Authorization": `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({
|
|
name: channelName || channel.name,
|
|
description: description || channel.description,
|
|
})
|
|
});
|
|
|
|
if (response.ok) {
|
|
setEditMode(false);
|
|
addAlert('success', 'Chaîne mise à jour avec succès');
|
|
fetchChannelData(); // Refresh channel data after update
|
|
} else {
|
|
console.error("Failed to update channel");
|
|
const errorData = await response.json();
|
|
addAlert('error', errorData.message || 'Erreur lors de la mise à jour de la chaîne');
|
|
}
|
|
} catch (error) {
|
|
console.error("Error updating channel:", error);
|
|
addAlert('error', 'Erreur lors de la mise à jour de la chaîne');
|
|
}
|
|
}
|
|
|
|
const onCloseAlert = (alertToRemove) => {
|
|
setAlerts(alerts.filter(alert => alert !== alertToRemove));
|
|
};
|
|
|
|
const addAlert = (type, message) => {
|
|
const newAlert = { type, message, id: Date.now() }; // Add unique ID
|
|
setAlerts([...alerts, newAlert]);
|
|
};
|
|
|
|
return (
|
|
<div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient">
|
|
<Navbar isSearchPage={false} alerts={alerts} onCloseAlert={onCloseAlert} />
|
|
|
|
<main className="pt-[118px] px-36 flex">
|
|
|
|
{/* LEFT SIDE */}
|
|
<form className="glassmorphism w-1/3 h-screen py-10 px-4">
|
|
<img src={user.picture} className="w-1/3 aspect-square object-cover rounded-full mx-auto" alt=""/>
|
|
<label htmlFor="name" className={`text-2xl text-white mb-1 block font-montserrat ${editMode ? "block" : "hidden"} `}>
|
|
Nom de chaine
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
value={channelName || channelName === "" ? channelName : channel ? channel.name : "Chargement"}
|
|
className={(editMode ? editModeClasses : nonEditModeClasses)}
|
|
onChange={(e) => setChannelName(e.target.value)}
|
|
placeholder="Nom d'utilisateur"
|
|
disabled={!editMode}
|
|
/>
|
|
|
|
<label htmlFor="name" className={`text-2xl text-white mb-1 block font-montserrat`}>
|
|
Description
|
|
</label>
|
|
<textarea
|
|
name="description"
|
|
id=""
|
|
className={(editMode ? editModeClassesTextArea : nonEditModeClassesTextArea)}
|
|
value={description || description === "" ? description : channel ? channel.description : "Chargement"}
|
|
onChange={(e) => setDescription(e.target.value)}
|
|
placeholder="Description de votre chaine"
|
|
disabled={!editMode}
|
|
></textarea>
|
|
|
|
{
|
|
editMode ? (
|
|
<div className="mt-4">
|
|
<button
|
|
type="button"
|
|
className="bg-primary p-3 rounded-sm text-white font-montserrat text-2xl font-black cursor-pointer"
|
|
onClick={handleUpdateChannel}
|
|
>
|
|
Enregistrer
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="bg-red-500 p-3 rounded-sm text-white font-montserrat text-2xl font-black cursor-pointer ml-3"
|
|
onClick={() => setEditMode(!editMode)}
|
|
>
|
|
Annuler
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
className="bg-primary p-3 rounded-sm text-white font-montserrat text-2xl font-black cursor-pointer mt-4"
|
|
onClick={() => setEditMode(!editMode)}
|
|
>
|
|
Modifier
|
|
</button>
|
|
)
|
|
}
|
|
|
|
</form>
|
|
|
|
{/* RIGHT SIDE */}
|
|
<div className="w-2/3 h-screen pl-10" >
|
|
{/* VIEW / SUBSCRIBERS STATS */}
|
|
|
|
<div className="flex gap-4" >
|
|
<div className="glassmorphism flex-1 h-32 flex flex-col justify-center items-center" >
|
|
{/* TOTAL VIEWS */}
|
|
<p className="text-white text-xl font-montserrat font-semibold" >Vues totales</p>
|
|
<p className="text-white text-2xl font-montserrat font-bold" >{channelStats ? channelStats.views : "0"}</p>
|
|
</div>
|
|
<div className="glassmorphism flex-1 h-32 flex flex-col justify-center items-center" >
|
|
{/* TOTAL SUBSCRIBERS */}
|
|
<p className="text-white text-xl font-montserrat font-semibold" >Abonnés</p>
|
|
<p className="text-white text-2xl font-montserrat font-bold" >{channelStats ? channelStats.subscribers : "0"}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* VIDEOS */}
|
|
<div className="flex justify-between">
|
|
<h2 className="text-white text-3xl font-montserrat font-bold mt-10" >Vidéos</h2>
|
|
<button
|
|
className="bg-primary px-2 py-1 rounded-sm text-white font-montserrat text-md font-semibold cursor-pointer mt-4"
|
|
onClick={() => navigate("/add-video")}
|
|
>
|
|
Ajouter une vidéo
|
|
</button>
|
|
|
|
</div>
|
|
|
|
{ channel?.videos?.length > 0 ? (
|
|
<div className="flex flex-col gap-4 mt-5">
|
|
{channel.videos.map((video) => (
|
|
<VideoStatListElement
|
|
video={video}
|
|
onClick={() => navigate("/manage-video/" + video.id)}
|
|
key={video.id}
|
|
/>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className="text-white text-xl font-montserrat mt-4">Aucune vidéo trouvée pour cette chaîne.</p>
|
|
)}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</main>
|
|
|
|
</div>
|
|
)
|
|
|
|
}
|