9 changed files with 185 additions and 44 deletions
@ -0,0 +1,113 @@ |
|||
import Navbar from "../components/Navbar.jsx"; |
|||
import {useEffect, useState} from "react"; |
|||
import {useParams} from "react-router-dom"; |
|||
import {fetchChannelDetails, subscribe} from "../services/channel.service.js"; |
|||
import TabLayout from "../components/TabLayout.jsx"; |
|||
import ChannelLastVideos from "../components/ChannelLastVideos.jsx"; |
|||
import { isSubscribed } from "../services/user.service.js"; |
|||
|
|||
|
|||
export default function Channel() { |
|||
|
|||
const id = useParams().id; |
|||
|
|||
const [alerts, setAlerts] = useState([]); |
|||
const [channel, setChannel] = useState(null); |
|||
const [isSubscribedToChannel, setIsSubscribedToChannel] = useState(false); |
|||
const tabs = [ |
|||
{ id: 'last', label: 'Dernières vidéos', element: () => <ChannelLastVideos videos={channel && channel.videos.slice(0, 10)} /> }, |
|||
{ id: 'all', label: 'Toutes les vidéos', element: () => <ChannelLastVideos videos={channel && channel.videos} /> }, |
|||
]; |
|||
|
|||
useEffect(() => { |
|||
async function fetchData() { |
|||
const chan = await fetchChannelDetails(id, addAlert); |
|||
setChannel(chan); |
|||
// If not authenticated, isSubscribed may be undefined -> default to false |
|||
const subscribed = await isSubscribed(id, addAlert); |
|||
setIsSubscribedToChannel(Boolean(subscribed)); |
|||
} |
|||
fetchData(); |
|||
}, [id]) |
|||
|
|||
const addAlert = (type, message) => { |
|||
const newAlert = { type, message, id: Date.now() }; // Add unique ID |
|||
setAlerts(prev => [...prev, newAlert]); |
|||
}; |
|||
const onCloseAlert = (alertToRemove) => { |
|||
setAlerts(alerts.filter(alert => alert !== alertToRemove)); |
|||
} |
|||
|
|||
const handleSubscribe = async () => { |
|||
try { |
|||
const result = await subscribe(id, addAlert); |
|||
// Update local counter from API response |
|||
const newCount = Number(result?.subscriptions ?? (channel?.subscriptions ?? 0)); |
|||
setChannel(prev => (prev ? { ...prev, subscriptions: newCount } : prev)); |
|||
|
|||
// Toggle local subscription state and notify |
|||
const next = !isSubscribedToChannel; |
|||
setIsSubscribedToChannel(next); |
|||
} catch (e) { |
|||
// Error alert already handled in service |
|||
} |
|||
}; |
|||
|
|||
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" > |
|||
|
|||
{/* Channel Header */} |
|||
<div className="glassmorphism p-4" > |
|||
<div className="flex items-center gap-4" > |
|||
<img |
|||
src={channel && channel.picture} |
|||
alt={channel && channel.name} |
|||
className="w-[192px] aspect-square object-cover rounded-full border-2 border-white" |
|||
/> |
|||
<div> |
|||
<h1 className="font-montserrat font-bold text-3xl text-white" >{channel && channel.name}</h1> |
|||
<p className="font-montserrat font-medium text-xl text-white" >{channel && channel.subscriptions} abonné(es)</p> |
|||
</div> |
|||
{ |
|||
isSubscribedToChannel ? ( |
|||
<button |
|||
className="ml-5 bg-primary text-white font-montserrat font-bold px-4 py-2 rounded-md cursor-pointer" |
|||
onClick={handleSubscribe} |
|||
> |
|||
se désabonner |
|||
</button> |
|||
) : ( |
|||
<button |
|||
className="ml-5 bg-primary text-white font-montserrat font-bold px-4 py-2 rounded-md cursor-pointer" |
|||
onClick={handleSubscribe} |
|||
> |
|||
s'abonner |
|||
</button> |
|||
) |
|||
} |
|||
</div> |
|||
|
|||
<h2 className="font-bold font-montserrat text-white text-xl mt-4" >Description</h2> |
|||
<p className="text-white text-lg font-medium font-montserrat pl-[24px]"> |
|||
{ channel && channel.description } |
|||
</p> |
|||
|
|||
</div> |
|||
|
|||
{/* Tab selector */} |
|||
|
|||
<TabLayout tabs={tabs}/> |
|||
|
|||
{/* 10 Last videos */} |
|||
|
|||
|
|||
|
|||
</main> |
|||
|
|||
</div> |
|||
) |
|||
|
|||
} |
|||
Loading…
Reference in new issue