diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 1c11065..b4631d7 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -16,6 +16,7 @@ import StreamDashboardPage from "./pages/StreamDashboardPage"; import { Brightness } from "./context/BrightnessContext"; import LoadingScreen from "./components/Layout/LoadingScreen"; import Following from "./pages/Following"; +import FollowedCategories from "./pages/FollowedCategories"; function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); @@ -98,6 +99,7 @@ function App() { }> } /> } /> + } /> } /> diff --git a/frontend/src/pages/FollowedCategories.tsx b/frontend/src/pages/FollowedCategories.tsx new file mode 100644 index 0000000..782e27d --- /dev/null +++ b/frontend/src/pages/FollowedCategories.tsx @@ -0,0 +1,151 @@ +import React, { useState, useEffect, useRef } from "react"; +import { useAuth } from "../context/AuthContext"; +import { useSidebar } from "../context/SidebarContext"; +import { CircleMinus, CirclePlus, Sidebar as SidebarIcon } from "lucide-react"; +import { useNavigate } from "react-router-dom"; +import { useParams } from "react-router-dom"; +import DynamicPageContent from "../components/Layout/DynamicPageContent"; +import { fetchContentOnScroll } from "../hooks/fetchContentOnScroll"; +import Button from "../components/Input/Button"; +import { useCategoryFollow } from "../hooks/useCategoryFollow"; +import { ListItemProps as StreamData } from "../components/Layout/ListItem"; +import LoadingScreen from "../components/Layout/LoadingScreen"; + +interface Category { + isFollowing: any; + 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 [streams, setStreams] = useState([]); + const listRowRef = useRef(null); + const isLoading = useRef(false); + const [streamOffset, setStreamOffset] = useState(0); + const [noStreams, setNoStreams] = useState(12); + const [hasMoreData, setHasMoreData] = useState(true); + const { + isCategoryFollowing, + checkCategoryFollowStatus, + followCategory, + unfollowCategory, + } = useCategoryFollow(); + + const toggleFollow = async (categoryId: number, categoryName: string) => { + try { + setFollowedCategories((prevCategories) => + prevCategories.map((category) => + category.category_id === categoryId + ? { + ...category, + isFollowing: !category.isFollowing + } + : category + ) + ); + + const category = followedCategories.find(cat => cat.category_id === categoryId); + + if (category?.isFollowing) { + await unfollowCategory(categoryName); + } else { + await followCategory(categoryName); + } + } catch (error) { + console.error("Error toggling follow state:", error); + } + }; + + useEffect(() => { + if (!isLoggedIn) return; + + const fetchFollowedCategories = async () => { + try { + const response = await fetch("/api/categories/following"); + 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]); + + useEffect(() => { + if (categoryName) checkCategoryFollowStatus(categoryName); + }, [categoryName]); + + if (hasMoreData && !streams.length) return ; + + return ( + <> + +
+
+ profile picture navigate(`/user/${username}`)} + /> +
+
+ Logged in as +
+ +
+
+ +
+ {followedCategories.map((category: Category) => ( +
+ + + {category.category_name} +
+ {category.category_name} +
+
+ ))} +
+
+
+ + ); +}; + +export default FollowedCategories; diff --git a/frontend/src/pages/Following.tsx b/frontend/src/pages/Following.tsx index 805c185..bbf9fce 100644 --- a/frontend/src/pages/Following.tsx +++ b/frontend/src/pages/Following.tsx @@ -20,7 +20,6 @@ const Following: React.FC = ({ extraClasses = "" }) => { const navigate = useNavigate(); const { username, isLoggedIn } = useAuth(); const [followedStreamers, setFollowedStreamers] = useState([]); - const [followedCategories, setFollowedCategories] = useState([]); // Fetch followed streamers useEffect(() => { @@ -30,7 +29,6 @@ const Following: React.FC = ({ extraClasses = "" }) => { if (!response.ok) throw new Error("Failed to fetch followed streamers"); const data = await response.json(); setFollowedStreamers(data.streamers || []); - setFollowedCategories(data.categories || []); } catch (error) { console.error("Error fetching followed streamers:", error); } diff --git a/frontend/src/pages/UserPage.tsx b/frontend/src/pages/UserPage.tsx index 2ca0cf5..606ec19 100644 --- a/frontend/src/pages/UserPage.tsx +++ b/frontend/src/pages/UserPage.tsx @@ -270,11 +270,11 @@ const UserPage: React.FC = () => { } onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} > - +
-
    -
  • - Category -
  • -
+ +