From 7e05778840e019a2e92b555a67c7444d956140b4 Mon Sep 17 00:00:00 2001 From: Khoa Vo Date: Thu, 14 May 2026 17:45:49 +0700 Subject: [PATCH] fix: sub/you tabs now use backend API, sidebar always visible on desktop, channel subscribe button wired up --- frontend/app/channel/[id]/page.tsx | 5 +- .../app/components/ChannelSubscribeButton.tsx | 51 ++++++++++++++++++ frontend/app/components/Header.tsx | 1 - frontend/app/context/SidebarContext.tsx | 17 +----- frontend/app/watch/ClientWatchPage.tsx | 52 ++++++++++++------- 5 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 frontend/app/components/ChannelSubscribeButton.tsx diff --git a/frontend/app/channel/[id]/page.tsx b/frontend/app/channel/[id]/page.tsx index b9a83f6..41a195a 100644 --- a/frontend/app/channel/[id]/page.tsx +++ b/frontend/app/channel/[id]/page.tsx @@ -1,4 +1,5 @@ import VideoCard from '../../components/VideoCard'; +import ChannelSubscribeButton from '../../components/ChannelSubscribeButton'; import { notFound } from 'next/navigation'; export const dynamic = 'force-dynamic'; @@ -93,9 +94,7 @@ export default async function ChannelPage({ {videos.length} videos - + diff --git a/frontend/app/components/ChannelSubscribeButton.tsx b/frontend/app/components/ChannelSubscribeButton.tsx new file mode 100644 index 0000000..3e7cf53 --- /dev/null +++ b/frontend/app/components/ChannelSubscribeButton.tsx @@ -0,0 +1,51 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +export default function ChannelSubscribeButton({ channelId, channelName }: { channelId: string; channelName: string }) { + const [subscribed, setSubscribed] = useState(false); + const [loading, setLoading] = useState(false); + + useEffect(() => { + fetch(`/api/subscribe?channel_id=${encodeURIComponent(channelId)}`) + .then(r => r.json()) + .then(data => setSubscribed(data.subscribed)) + .catch(() => setSubscribed(false)); + }, [channelId]); + + const handleSubscribe = async () => { + if (loading || !channelId) return; + setLoading(true); + try { + if (subscribed) { + const res = await fetch(`/api/subscribe?channel_id=${encodeURIComponent(channelId)}`, { method: 'DELETE' }); + if (res.ok) setSubscribed(false); + } else { + const res = await fetch('/api/subscribe', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + channel_id: channelId, + channel_name: channelName || channelId, + channel_avatar: channelName ? channelName[0].toUpperCase() : '?', + }), + }); + if (res.ok) setSubscribed(true); + } + } catch (error) { + console.error('Subscribe error:', error); + } finally { + setLoading(false); + } + }; + + return ( + + ); +} diff --git a/frontend/app/components/Header.tsx b/frontend/app/components/Header.tsx index 2df77a4..7154db0 100644 --- a/frontend/app/components/Header.tsx +++ b/frontend/app/components/Header.tsx @@ -41,7 +41,6 @@ export default function Header() { {/* Left */}