27 changed files with 2283 additions and 496 deletions
File diff suppressed because it is too large
@ -0,0 +1,95 @@ |
|||||
|
import React from "react"; |
||||
|
import Navbar from "../components/Navbar"; |
||||
|
import { useEffect, useState } from "react"; |
||||
|
import { getAllUserSubscriptions, getAllUserSubscriptionVideos } from "../services/user.service.js"; |
||||
|
import { useAuth } from "../contexts/AuthContext.jsx"; |
||||
|
import VideoCard from "../components/VideoCard.jsx"; |
||||
|
import { useNavigate } from "react-router-dom"; |
||||
|
|
||||
|
export default function Subscription() { |
||||
|
|
||||
|
const navigate = useNavigate(); |
||||
|
|
||||
|
const [alerts, setAlerts] = useState([]); |
||||
|
const [subscriptions, setSubscriptions] = React.useState([]); |
||||
|
const [videos, setVideos] = useState([]); |
||||
|
const {user, isAuth} = useAuth(); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
fetchSubscriptions(); |
||||
|
fetchSubscriptionVideos(); |
||||
|
}, []); |
||||
|
|
||||
|
const fetchSubscriptions = async () => { |
||||
|
const token = localStorage.getItem('token'); |
||||
|
if (!token) { |
||||
|
addAlert('error', "User not authenticated"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const data = await getAllUserSubscriptions(user.id, token, addAlert); |
||||
|
if (data) { |
||||
|
setSubscriptions(data); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const fetchSubscriptionVideos = async () => { |
||||
|
const token = localStorage.getItem('token'); |
||||
|
if (!token) { |
||||
|
addAlert('error', "User not authenticated"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const data = await getAllUserSubscriptionVideos(user.id, token, addAlert); |
||||
|
if (data) { |
||||
|
setVideos(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)); |
||||
|
}; |
||||
|
|
||||
|
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="px-5 lg:px-36 w-full pt-[48px] lg:pt-[118px] lg:flex gap-8"> |
||||
|
|
||||
|
{/* LEFT SIDE (subscription list) */} |
||||
|
<div className="w-full lg:w-1/4 border-b border-gray-200 lg:border-b-0 mb-8 lg:mb-0 pb-2 lg:pb-0"> |
||||
|
<h2 className="text-2xl text-white font-montserrat font-semibold mb-4">Mes Abonnements</h2> |
||||
|
<ul className="space-y-2"> |
||||
|
{subscriptions.map(subscription => ( |
||||
|
<li |
||||
|
key={subscription.id} |
||||
|
className="p-2 flex items-center lg:border-r lg:border-gray-200 glassmorphism w-max lg:w-auto" |
||||
|
onClick={() => navigate(`/channel/${subscription.channel_id}`)} |
||||
|
> |
||||
|
<img |
||||
|
src={subscription.picture} |
||||
|
alt={subscription.channel_name} |
||||
|
className="w-14 aspect-square rounded-full inline-block mr-2 align-middle" |
||||
|
/> |
||||
|
<p className="text-white text-lg font-montserrat font-medium" >{subscription.channel_name}</p> |
||||
|
</li> |
||||
|
))} |
||||
|
</ul> |
||||
|
</div> |
||||
|
|
||||
|
{/* RIGHT SIDE (videos from subscriptions) */} |
||||
|
<div className="flex-1 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> |
||||
|
{videos.map(video => ( |
||||
|
<VideoCard key={video.id} video={video} /> |
||||
|
))} |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</main> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
Loading…
Reference in new issue