diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3c69ec3..ead5d55 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -15,9 +15,12 @@ import DashboardPage from "./pages/DashboardPage"; import { Brightness } from "./context/BrightnessContext"; import LoadingScreen from "./components/Layout/LoadingScreen"; import Following from "./pages/Following"; +<<<<<<< HEAD import FollowedCategories from "./pages/FollowedCategories"; import UnsubscribeForm from "./components/Auth/UnsubscribeForm"; import UnsubscribePage from "./pages/UnsubscribePage"; +======= +>>>>>>> 2494e40ffd09ee704397c812f63d03bb7ec156f1 function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); @@ -79,7 +82,6 @@ function App() { }> } /> } /> - } /> } /> diff --git a/frontend/src/pages/FollowedCategories.tsx b/frontend/src/pages/FollowedCategories.tsx deleted file mode 100644 index c71633d..0000000 --- a/frontend/src/pages/FollowedCategories.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useState, useEffect, useRef } from "react"; -import { useAuth } from "../context/AuthContext"; -import { useNavigate, useParams } from "react-router-dom"; -import DynamicPageContent from "../components/Layout/DynamicPageContent"; -import { useCategoryFollow } from "../hooks/useCategoryFollow"; -import FollowButton from "../components/Input/FollowButton"; -import { useAuthModal } from "../hooks/useAuthModal"; - - -interface Category { - isFollowing: boolean; - category_id: number; - category_name: string; -} - -interface FollowedCategoryProps { - extraClasses?: string; -} - -const FollowedCategories: React.FC = ({ extraClasses = "" }) => { - const navigate = useNavigate(); - const { username, isLoggedIn } = useAuth(); - const [followedCategories, setFollowedCategories] = useState([]); - const { categoryName } = useParams<{ categoryName: string }>(); - const { checkCategoryFollowStatus, followCategory, unfollowCategory } = useCategoryFollow(); - - - useEffect(() => { - if (categoryName) checkCategoryFollowStatus(categoryName); - }, [categoryName]); - - useEffect(() => { - if (!isLoggedIn) return; - - const fetchFollowedCategories = async () => { - try { - const response = await fetch("/api/categories/your_categories"); - if (!response.ok) throw new Error("Failed to fetch followed categories"); - const data = await response.json(); - setFollowedCategories(data); - } catch (error) { - console.error("Error fetching followed categories:", error); - } - }; - - fetchFollowedCategories(); - }, [isLoggedIn]); - - - return ( - - - - ); -}; - -export default FollowedCategories; diff --git a/frontend/src/pages/Following.tsx b/frontend/src/pages/Following.tsx index 6566110..b4a43c4 100644 --- a/frontend/src/pages/Following.tsx +++ b/frontend/src/pages/Following.tsx @@ -1,71 +1,81 @@ import React, { useEffect, useState } from "react"; import { useAuth } from "../context/AuthContext"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import DynamicPageContent from "../components/Layout/DynamicPageContent"; import { useFollow } from "../hooks/useFollow"; -import { useAuthModal } from "../hooks/useAuthModal"; import FollowUserButton from "../components/Input/FollowUserButton"; +import FollowButton from "../components/Input/FollowButton"; interface Streamer { - user_id: number; - username: string; + user_id: number; + username: string; } -interface FollowingStreamerProps { +interface Category { + isFollowing: boolean; + category_id: number; + category_name: string; +} + +interface FollowingProps { extraClasses?: string; } -const Following: React.FC = ({ extraClasses = "" }) => { +const Following: React.FC = ({ extraClasses = "" }) => { const navigate = useNavigate(); const { isLoggedIn } = useAuth(); const [followedStreamers, setFollowedStreamers] = useState([]); - const [followingStatus, setFollowingStatus] = useState<{ [key: number]: boolean }>({}); // Store follow status for each streamer + const [followedCategories, setFollowedCategories] = useState([]); + const [followingStatus, setFollowingStatus] = useState<{ [key: number]: boolean }>({}); - const { isFollowing, checkFollowStatus, followUser, unfollowUser } = - useFollow(); + const { checkFollowStatus, followUser, unfollowUser } = useFollow(); + + const location = useLocation(); + const queryParams = new URLSearchParams(location.search); + const initialTab = queryParams.get("tab") === "streamers" ? "categories" : "categories"; + + const [activeTab, setActiveTab] = useState<"categories" | "streamers">(initialTab); + //const [followingStatus, setFollowingStatus] = useState>({}); useEffect(() => { - const fetchFollowedStreamers = async () => { + const newTab = queryParams.get("tab") as "categories" | "streamers"; + if (newTab) { + setActiveTab(newTab); + } + }, [location.search]); + + useEffect(() => { + const fetchFollowedContent = async () => { try { const response = await fetch("/api/user/following"); - if (!response.ok) throw new Error("Failed to fetch followed streamers"); - const data = await response.json(); - setFollowedStreamers(data); + if (!response.ok) throw new Error("Failed to fetch followed content"); + const data = await response.json(); + if (!Array.isArray(data.streams) || !Array.isArray(data.categories)) { + throw new Error("API response structure is incorrect"); + } + + setFollowedStreamers(data.streams); + setFollowedCategories(data.categories); + + // Fetch follow status for streamers const updatedStatus: { [key: number]: boolean } = {}; - for (const streamer of data || []) { + for (const streamer of data.streams) { const status = await checkFollowStatus(streamer.username); updatedStatus[streamer.user_id] = Boolean(status); } setFollowingStatus(updatedStatus); - - console.log("Fetched Follow Status:", updatedStatus); // Log the status } catch (error) { - console.error("Error fetching followed streamers:", error); + console.error("Error fetching followed content:", error); + setFollowedStreamers([]); + setFollowedCategories([]); } }; - if (isLoggedIn) { - fetchFollowedStreamers(); - } - }, [isLoggedIn]); - - - const handleFollowToggle = async (userId: number) => { - const isCurrentlyFollowing = followingStatus[userId]; - - if (isCurrentlyFollowing) { - await unfollowUser(userId); - } else { - await followUser(userId); + if (isLoggedIn) { + fetchFollowedContent(); } - - // Update local state for this specific streamer - setFollowingStatus((prev) => ({ - ...prev, - [userId]: !isCurrentlyFollowing, // Toggle based on previous state - })); - }; + }, [isLoggedIn]); return ( @@ -73,28 +83,59 @@ const Following: React.FC = ({ extraClasses = "" }) => { id="sidebar" 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}`} > -
- {followedStreamers.map((streamer: any) => ( -
navigate(`/user/${streamer.username}`)}*/ - > - {streamer.username} - -
- ))} -
+ {activeTab === "streamers" && ( +
+ {followedStreamers.map((streamer: any) => ( +
navigate(`/user/${streamer.username}`)}*/ + > + {streamer.username} + +
+ ))} +
+ )} + + {activeTab === "categories" && ( +
+ {followedCategories.map((category) => { + return ( +
navigate(`/category/${category.category_name}`)} + > + + {category.category_name} +
+ {category.category_name} +
+
+ ); + })} + +
+ )}; + -
+ + + + ); }; diff --git a/frontend/src/pages/UserPage.tsx b/frontend/src/pages/UserPage.tsx index 4bd80dc..f97a394 100644 --- a/frontend/src/pages/UserPage.tsx +++ b/frontend/src/pages/UserPage.tsx @@ -82,13 +82,13 @@ const UserPage: React.FC = () => { const handleNavigation = (path: string) => { if (profilePicture === initialProfilePicture.current) { - // Variable hasn't changed - use React Router navigation - navigate(path); + // Variable hasn't changed - use React Router navigation + navigate(path); } else { - // Variable has changed - use full page reload - window.location.href = path; + // Variable has changed - use full page reload + window.location.href = path; } - }; + }; // Store initial profile picture to know if it changes later useEffect(() => { @@ -138,8 +138,7 @@ const UserPage: React.FC = () => { {/* Profile Picture */}
@@ -269,7 +268,7 @@ const UserPage: React.FC = () => { onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")} onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} > -
@@ -289,7 +288,7 @@ const UserPage: React.FC = () => { onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")} onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} > - +