diff --git a/frontend/config.tsx b/frontend/config.tsx deleted file mode 100644 index 59de80b..0000000 --- a/frontend/config.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export const paths = { - pfps: "", - category_thumbnails: "", - icons: "", -}; diff --git a/frontend/src/hooks/useSameUser.ts b/frontend/src/hooks/useSameUser.ts deleted file mode 100644 index 6bf874a..0000000 --- a/frontend/src/hooks/useSameUser.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useEffect, useState } from "react" - -export function useSameUser({ username }: { username: string | undefined }) { - const [isSame, setIsSame] = useState(false); - - useEffect(() => { - const fetchStatus = async () => { - try { - const response = await fetch(`/api/user/same/${username}`); - if (!response.ok) { - throw new Error("Failed to validate user"); - } - const data = await response.json(); - setIsSame(data.same); - } catch (error) { - console.error("Error:", error); - } - }; - - fetchStatus(); - }, []); - - return isSame; -} \ No newline at end of file diff --git a/frontend/src/pages/UserPage.tsx b/frontend/src/pages/UserPage.tsx index ee3381c..fcffa20 100644 --- a/frontend/src/pages/UserPage.tsx +++ b/frontend/src/pages/UserPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback } from "react"; import AuthModal from "../components/Auth/AuthModal"; import { useAuthModal } from "../hooks/useAuthModal"; import { useAuth } from "../context/AuthContext"; @@ -10,8 +10,8 @@ import DynamicPageContent from "../components/Layout/DynamicPageContent"; import LoadingScreen from "../components/Layout/LoadingScreen"; import { StreamListItem } from "../components/Layout/ListItem"; import { EditIcon } from "lucide-react"; -import { getCategoryThumbnail } from "../utils/thumbnailUtils"; -import { useSameUser } from "../hooks/useSameUser"; +import ListRow from "../components/Layout/ListRow"; +import { useStreams, useVods } from "../hooks/useContent"; interface UserProfileData { id: number; @@ -20,22 +20,38 @@ interface UserProfileData { followerCount: number; isPartnered: boolean; isLive: boolean; - currentStreamTitle?: string; - currentStreamCategory?: string; - currentStreamViewers?: number; - currentStreamStartTime?: string; - currentStreamThumbnail?: string; } const UserPage: React.FC = () => { - const [userPageVariant, setUserPageVariant] = useState<"personal" | "streamer" | "user" | "admin">("user"); + const [userPageVariant, setUserPageVariant] = useState<"personal" | "user" | "admin">("user"); const [profileData, setProfileData] = useState(); const { isFollowing, checkFollowStatus, followUser, unfollowUser } = useFollow(); const { showAuthModal, setShowAuthModal } = useAuthModal(); const { username: loggedInUsername } = useAuth(); const { username } = useParams(); - const isUser = useSameUser({ username }); + const { vods } = useVods(`/api/vods/${username}`); const navigate = useNavigate(); + const { streams } = useStreams(`/api/streams/${username}/data`); + const currentStream = streams[0]; + + const fetchProfileData = useCallback(async () => { + try { + // Profile data + const profileResponse = await fetch(`/api/user/${username}`); + const profileData = await profileResponse.json(); + setProfileData({ + id: profileData.user_id, + username: profileData.username, + bio: profileData.bio || "This user hasn't written a bio yet.", + followerCount: profileData.num_followers || 0, + isPartnered: profileData.isPartnered || false, + isLive: profileData.is_live, + }); + } catch (err) { + console.error("Error fetching profile data:", err); + window.location.href = "/404"; + } + }, [username]); // Saves uploaded image as profile picture for the user const saveUploadedImage = async (event: React.ChangeEvent) => { @@ -62,58 +78,20 @@ const UserPage: React.FC = () => { } }; + // Check if the current user is the currently logged-in user useEffect(() => { - // Fetch user profile data - fetch(`/api/user/${username}`) - .then((res) => res.json()) - .then((data) => { - setProfileData({ - id: data.user_id, - username: data.username, - bio: data.bio || "This user hasn't written a bio yet.", - followerCount: data.num_followers || 0, - isPartnered: data.isPartnered || false, - isLive: data.is_live, - currentStreamTitle: "", - currentStreamCategory: "", - currentStreamViewers: 0, - currentStreamThumbnail: "", - }); + if (username === loggedInUsername) setUserPageVariant("personal"); + // else if (data.isAdmin) setUserPageVariant("admin"); + else setUserPageVariant("user"); - if (data.is_live) { - // Fetch stream data for this streamer - fetch(`/api/streams/${data.user_id}/data`) - .then((res) => res.json()) - .then((streamData) => { - setProfileData((prevData) => { - if (!prevData) return prevData; - return { - ...prevData, - currentStreamTitle: streamData.title, - currentStreamCategory: streamData.category_id, - currentStreamViewers: streamData.num_viewers, - currentStreamStartTime: streamData.start_time, - currentStreamThumbnail: getCategoryThumbnail(streamData.category_name, streamData.thumbnail), - }; - }); - let variant: "user" | "streamer" | "personal" | "admin"; - if (username === loggedInUsername) variant = "personal"; - else if (streamData.title) variant = "streamer"; - // else if (data.isAdmin) variant = "admin"; - else variant = "user"; - setUserPageVariant(variant); - }) - .catch((err) => console.error("Error fetching stream data:", err)); - } - }) - .catch((err) => { - console.error("Error fetching profile data:", err); - navigate("/404"); - }); - - // Check if the *logged-in* user is following this user if (loggedInUsername && username) checkFollowStatus(username); - }, [username]); + }, [username, loggedInUsername, checkFollowStatus]); + + // Fetch user profile data + useEffect(() => { + if (!username) return; + fetchProfileData(); + }, [fetchProfileData]); if (!profileData) return ; @@ -148,16 +126,21 @@ const UserPage: React.FC = () => { } inset-0 z-20`} style={{ boxShadow: "var(--user-pfp-border-shadow)" }} > -