+
{review.userId.firstName} {review.userId.lastName}
+
{review.role}
diff --git a/frontend/src/Pages/Profile.jsx b/frontend/src/Pages/Profile.jsx
new file mode 100644
index 00000000..b930e4b4
--- /dev/null
+++ b/frontend/src/Pages/Profile.jsx
@@ -0,0 +1,211 @@
+import { useState, useEffect } from 'react'
+import { useParams } from 'react-router-dom'
+import axios from 'axios'
+
+export default function UserProfile() {
+ const { id } = useParams() // Get the user ID from the URL params
+ const backendURL = import.meta.env.VITE_BACKEND_URL
+ const token = JSON.parse(localStorage.getItem("tastytoken")) // Token still comes from local storage for authentication
+
+ const [username, setUsername] = useState("ChefJulia")
+ const [bio, setBio] = useState("Passionate about creating delicious, healthy recipes that anyone can make!")
+ const [imagePreview, setImagePreview] = useState("/placeholder.svg?height=128&width=128")
+ const [recipes, setRecipes] = useState([])
+ const [likedRecipes, setLikedRecipes] = useState([]) // Added state for liked recipes
+ const [following, setFollowing] = useState(false)
+ const [followingCount, setFollowingCount] = useState(false)
+ const [followers, setFollowers] = useState(0)
+ const [activeTab, setActiveTab] = useState('recipes')
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState(null)
+
+ useEffect(() => {
+ // Fetch user information
+ const fetchUserImage = () => {
+ axios
+ .post(`${backendURL}/api/user/fetch`, { id }, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ })
+ .then((res) => {
+ setUsername(res.data.username)
+ setBio(res.data.bio)
+ setImagePreview(res.data.profile)
+ setFollowingCount(res.data.following.length)
+ setFollowers(res.data.followers.length)
+ })
+ .catch((err) => {
+ console.error("Error fetching user data", err)
+ })
+ }
+
+ // Fetch recipes
+ const fetchRecipes = () => {
+ setLoading(true)
+ setError(null)
+ axios
+ .post(`${backendURL}/api/recipe/readall`, { id: id }, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ })
+ .then((res) => {
+ setRecipes(res.data.recipes)
+ })
+ .catch((err) => {
+ console.error("Error fetching recipes:", err)
+ setError("Failed to fetch recipes. Please try again.")
+ })
+ .finally(() => setLoading(false))
+ }
+
+ // Fetch liked recipes
+ const fetchLikedRecipes = () => {
+ axios
+ .post(
+ `${backendURL}/api/recipe/liked_recipes`,
+ { userId: id }, // Use the user ID from URL params
+ {
+ headers: { Authorization: `Bearer ${token}` },
+ }
+ )
+ .then((res) => {
+ setLikedRecipes(res.data.likedRecipes)
+ })
+ .catch((err) => {
+ console.error("Error fetching liked recipes:", err)
+ setError("Failed to fetch liked recipes. Please try again.")
+ })
+ }
+
+ fetchUserImage()
+ fetchRecipes()
+ fetchLikedRecipes() // Call the fetchLikedRecipes function to get liked recipes
+ }, [id, backendURL, token]) // Use id, backendURL, and token in dependencies
+
+ const handleFollow = () => {
+ setFollowing(!following)
+ setFollowers(followers + (following ? -1 : 1))
+ }
+
+ return (
+
+ {/* Banner and Profile Picture */}
+
+
+
+
+
+
+ {/* User Info */}
+
+
+
+
+
+
+ {/* User Stats */}
+
+ {recipes.length} Recipes
+ {followers} Followers
+ {followingCount} Following
+
+
+
+ {/* Tabs for Recipes and Liked Recipes */}
+
+
+
+
+
+
+ {activeTab === 'recipes' && (
+
+ {loading ? (
+
Loading recipes...
+ ) : error ? (
+
{error}
+ ) : recipes.length > 0 ? (
+ recipes.map((recipe) => (
+
+
+
+
{recipe.name}
+
{recipe.description}
+
+ ⭐ {recipe.rating}
+ 👍 {recipe.likes}
+
+
+
+ ))
+ ) : (
+
No recipes posted
+ )}
+
+ )}
+
+ {activeTab === 'liked' && (
+
+ {loading ? (
+
Loading liked recipes...
+ ) : error ? (
+
{error}
+ ) : likedRecipes.length > 0 ? (
+ likedRecipes.map((recipe) => (
+
+
+
+
{recipe.name}
+
{recipe.description}
+
+ ⭐ {recipe.rating}
+ 👍 {recipe.likes}
+
+
+
+ ))
+ ) : (
+
No liked recipes
+ )}
+
+ )}
+
+
+ )
+}