import VideoCard from '../../components/VideoCard'; import { notFound } from 'next/navigation'; export const dynamic = 'force-dynamic'; interface ChannelInfo { id: string; title: string; subscriber_count: number; avatar: string; } interface VideoData { id: string; title: string; uploader: string; thumbnail: string; view_count: number; duration: string; } // Helper to format subscribers function formatSubscribers(count: number): string { if (count >= 1000000) return (count / 1000000).toFixed(2) + 'M'; if (count >= 1000) return (count / 1000).toFixed(0) + 'K'; return count.toString(); } // We no longer need getAvatarColor as we now use the global --yt-avatar-bg async function getChannelInfo(id: string) { try { const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:8080'}/api/channel/info?id=${id}`, { cache: 'no-store' }); if (!res.ok) return null; return res.json() as Promise; } catch (e) { console.error(e); return null; } } async function getChannelVideos(id: string) { try { const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:8080'}/api/channel/videos?id=${id}&limit=30`, { cache: 'no-store' }); if (!res.ok) return []; return res.json() as Promise; } catch (e) { console.error(e); return []; } } export default async function ChannelPage({ params, }: { params: Promise<{ id: string }> }) { const awaitParams = await params; let channelId = awaitParams.id; // Clean up URL encoding issues if any channelId = decodeURIComponent(channelId); const [info, videos] = await Promise.all([ getChannelInfo(channelId), getChannelVideos(channelId) ]); if (!info) { return notFound(); } return (
{/* Channel Header */}
{info.avatar}

{info.title}

{info.id} {formatSubscribers(info.subscriber_count)} subscribers {videos.length} videos
{/* Navigation Tabs */}
Videos {videos.length}
{/* Video Grid */}
{videos.map((v, i) => { // Enforce correct channel name v.uploader = info.title; const stagger = `stagger-${Math.min(i + 1, 6)}`; return (
); })}
); }