STYLE: Added Styling for Categories, Vods and Following

This commit is contained in:
EvanLin3141
2025-03-04 00:19:07 +00:00
parent 12c09fe261
commit 082b01ef51
2 changed files with 105 additions and 85 deletions

View File

@@ -5,6 +5,7 @@ import DynamicPageContent from "../components/Layout/DynamicPageContent";
import { useFollow } from "../hooks/useFollow"; import { useFollow } from "../hooks/useFollow";
import FollowUserButton from "../components/Input/FollowUserButton"; import FollowUserButton from "../components/Input/FollowUserButton";
import FollowButton from "../components/Input/FollowButton"; import FollowButton from "../components/Input/FollowButton";
import Footer from "../components/Layout/Footer";
interface Streamer { interface Streamer {
user_id: number; user_id: number;
@@ -78,63 +79,62 @@ const Following: React.FC<FollowingProps> = ({ extraClasses = "" }) => {
}, [isLoggedIn]); }, [isLoggedIn]);
return ( return (
<DynamicPageContent> <DynamicPageContent className="overflow-x-hidden h-full">
<div <div className="flex items-center justify-center mb-20">
id="sidebar" <div
className={`top-0 left-0 w-screen h-screen overflow-x-hidden flex flex-col bg-[var(--sideBar-bg)] text-[var(--sideBar-text)] text-center overflow-y-auto scrollbar-hide transition-all duration-500 ease-in-out ${extraClasses}`} id="follow_page"
> className={`w-[96vw] h-full bg-slate-50/35 rounded-lg overflow-x-hidden flex flex-col text-center scrollbar-hide transition-all duration-500 ease-in-out ${extraClasses}`}
{activeTab === "streamers" && ( >
<div {activeTab === "streamers" && (
id="followed-users" <div
className={`grid grid-cols-2 gap-4 p-4 w-full`}> id="followed-users"
{followedStreamers.map((streamer: any) => ( className={`grid grid-cols-2 gap-4 p-4 w-full`}>
<div {followedStreamers.map((streamer: any) => (
key={`streamer-${streamer.username}`}
className="cursor-pointer bg-black w-full py-2 border border-[--text-color] rounded-lg text-white hover:text-purple-500 font-bold transition-colors"
/*onClick={() => navigate(`/user/${streamer.username}`)}*/
>
{streamer.username}
<FollowUserButton
user={{
user_id: streamer.user_id,
username: streamer.username,
isFollowing: followingStatus[streamer.user_id] || true,
}}
/>
</div>
))}
</div>
)}
{activeTab === "categories" && (
<div id="categories-followed" className="grid grid-cols-4 gap-4 p-4 w-full">
{followedCategories.map((category) => {
return (
<div <div
key={category.category_id} key={`streamer-${streamer.username}`}
className="relative flex flex-col items-center justify-center border border-[--text-color] rounded-lg overflow-hidden hover:shadow-lg transition-all" className="h-full cursor-pointer bg-black w-full py-2 rounded-lg text-white hover:text-purple-500 font-bold transition-colors"
onClick={() => navigate(`/category/${category.category_name}`)} /*onClick={() => navigate(`/user/${streamer.username}`)}*/
> >
<FollowButton category={category} /> {streamer.username}
<img <FollowUserButton
src={`/images/category_thumbnails/${category.category_name.toLowerCase().replace(/ /g, "_")}.webp`} user={{
alt={category.category_name} user_id: streamer.user_id,
className="w-full h-28 object-cover" username: streamer.username,
isFollowing: followingStatus[streamer.user_id] || true,
}}
/> />
<div className="absolute bottom-2 bg-black bg-opacity-60 w-full text-center text-white py-1">
{category.category_name}
</div>
</div> </div>
); ))}
})} </div>
)}
</div> {activeTab === "categories" && (
)}; <div id="categories-followed" className="grid grid-cols-3 gap-4 p-10 w-full">
{followedCategories.map((category) => {
return (
<div
key={category.category_id}
className="relative flex flex-col items-center justify-center rounded-lg overflow-hidden hover:shadow-lg transition-all"
onClick={() => navigate(`/category/${category.category_name}`)}
>
<FollowButton category={category} />
<img
src={`/images/category_thumbnails/${category.category_name.toLowerCase().replace(/ /g, "_")}.webp`}
alt={category.category_name}
className="w-full h-[200px] object-cover"
/>
<div className="absolute bottom-2 bg-black bg-opacity-60 w-full text-center text-white py-1">
{category.category_name}
</div>
</div>
)
})}
</div>
)};
</div>
</div> </div>
<Footer />
</DynamicPageContent > </DynamicPageContent >
); );
}; };

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
import { useAuth } from "../context/AuthContext"; import { useAuth } from "../context/AuthContext";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import DynamicPageContent from "../components/Layout/DynamicPageContent"; import DynamicPageContent from "../components/Layout/DynamicPageContent";
import Footer from "../components/Layout/Footer";
interface Vod { interface Vod {
vod_id: number; vod_id: number;
@@ -46,45 +47,64 @@ const Vods: React.FC = () => {
if (error) return <p className="text-center text-red-500">{error}</p>; if (error) return <p className="text-center text-red-500">{error}</p>;
return ( return (
<DynamicPageContent> <DynamicPageContent className="h-full">
<div className="p-4"> <div className="mt-[3em] w-screen h-[100vh] max-h-[500px] flex items-center justify-center">
<h1 className="text-2xl font-bold mb-4">{username}'s VODs</h1> <div
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> id="follow_page"
{ownedVods.length === 0 ? ( className={`w-[96vw] h-full bg-slate-50/35 rounded-lg overflow-x-hidden flex flex-col text-center scrollbar-hide transition-all duration-500 ease-in-out`}
<p className="col-span-full text-center">No VODs available.</p> >
) : ( <div className="p-4">
ownedVods.map((vod) => { <h1 className="text-2xl font-bold mb-4">{username}'s VODs</h1>
const thumbnailUrl = `/stream/${username}/vods/${vod.vod_id}.png`; <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{ownedVods.length === 0 ? (
<p className="col-span-full text-center">No VODs available.</p>
) : (
ownedVods.map((vod) => {
const thumbnailUrl = `/stream/${username}/vods/${vod.vod_id}.png`;
return ( return (
<div <div
key={vod.vod_id} key={vod.vod_id}
className="border rounded-lg p-4 bg-gray-800 text-white cursor-pointer hover:bg-gray-700 transition" className="mt-5 h-full rounded-lg p-4 bg-gray-800 text-white cursor-pointer hover:bg-gray-700 transition"
onClick={() => navigate(`/stream/${username}/vods/${vod.vod_id}`)} onClick={() => navigate(`/stream/${username}/vods/${vod.vod_id}`)}
> >
{/* Thumbnail */} {/* Thumbnail */}
<img <img
src={thumbnailUrl} src={thumbnailUrl}
alt={`Thumbnail for ${vod.title}`} alt={`Thumbnail for ${vod.title}`}
className="w-full h-40 object-cover rounded-md mb-2" className="w-full h-[200px] object-cover rounded-md mb-2"
onError={(e) => { onError={(e) => {
e.currentTarget.onerror = null; e.currentTarget.onerror = null;
e.currentTarget.src = "/default-thumbnail.png"; e.currentTarget.src = "/default-thumbnail.png";
}} }}
/> />
{/* Video Info */}
<div className="flex flex-col space-y-1">
{/* Video Info */} {/* Video Title */}
<h2 className="text-lg font-semibold">{vod.title}</h2> <h2 className="text-white font-bold text-lg">{vod.title}</h2>
<p className="text-sm">📅 {new Date(vod.datetime).toLocaleString()}</p>
<p className="text-sm">🎮 {vod.category_name}</p> {/* Channel Name */}
<p className="text-sm"> {Math.floor(vod.length / 60)} min</p> <div className="flex items-center space-x-2">
<p className="text-sm">👀 {vod.views} views</p> <p className="text-white text-sm">{username}</p>
</div> </div>
);
}) {/* Views and Date */}
)} <div className="flex space-x-2 text-white text-sm">
<p>{vod.views} views</p>
<p>{new Date(vod.datetime).toLocaleString()}</p>
</div>
</div>
</div>
);
})
)}
</div>
</div>
</div> </div>
</div> </div>
<Footer />
</DynamicPageContent> </DynamicPageContent>
); );
}; };