Skip to content

Commit

Permalink
follow-feature-update
Browse files Browse the repository at this point in the history
  • Loading branch information
IkkiOcean committed Nov 9, 2024
1 parent 666606f commit 2edca11
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 11 deletions.
59 changes: 59 additions & 0 deletions backend/Controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,69 @@ const deleteUserById = async (req, res) => {
};


const toggleFollowUser = async (req, res) => {
const { userId, username: followerUsername } = req.body;
try {
// Check if the target user exists
const targetUser = await User.findById(userId);
if (!targetUser) {
return res.status(404).json({ message: "User not found" });
}

// Find the logged-in user by their username
const loggedInUser = await User.findOne({ username: followerUsername });

if (!loggedInUser) {
return res.status(404).json({ message: "Logged-in user not found" });
}

// Check if already following
const isFollowing = targetUser.followers.includes(loggedInUser._id);

if (isFollowing) {
// Unfollow: Remove the target user from logged-in user's following and vice versa
targetUser.followers = targetUser.followers.filter(
(followerId) => followerId.toString() !== loggedInUser._id.toString()
);
loggedInUser.following = loggedInUser.following.filter(
(followingId) => followingId.toString() !== targetUser._id.toString()
);
await targetUser.save();
await loggedInUser.save();

return res.status(200).json({
message: `Successfully unfollowed ${targetUser.username}`,
username: targetUser.username,
followingCount: loggedInUser.following.length,
followersCount: targetUser.followers.length,
});
} else {
// Follow: Add the target user to logged-in user's following and vice versa
targetUser.followers.push(loggedInUser._id);
loggedInUser.following.push(targetUser._id);
await targetUser.save();
await loggedInUser.save();

return res.status(200).json({
message: `Successfully followed ${targetUser.username}`,
username: targetUser.username,
followingCount: loggedInUser.following.length,
followersCount: targetUser.followers.length,
});
}
} catch (error) {
console.error("Error toggling follow status:", error);
res.status(500).json({ message: "Internal server error" });
}
};



const UserController = {
Signup,
Login,
getAllUserName,
toggleFollowUser,
deleteUserById,
verifyUserByToken,
forgotPassword,
Expand Down
1 change: 1 addition & 0 deletions backend/routes/web.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ router.get("/recipe/getcomments/:recipeId", RecipeController.getComments);
router.post("/signup", UserController.Signup);
router.post("/login", UserController.Login);
router.post("/submitFeedback", UserController.submitFeedback);
router.post("/follow", UserController.toggleFollowUser);
router.get('/feedback', UserController.getAllFeedback);
router.get('/feedback/:id', UserController.getFeedbackByUserId);
router.post("/feedback/delete", UserController.deleteFeedbackById);
Expand Down
34 changes: 30 additions & 4 deletions frontend/src/Pages/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const Dashboard = () => {
const backendURL = import.meta.env.VITE_BACKEND_URL;
const token = JSON.parse(localStorage.getItem("tastytoken"));
const user = useLocation().state.user;
const [userData, setUserData] = useState(null)
const path = useLocation().pathname;
const [loading, setLoading] = useState(true);
const [isModalOpen, setModalOpen] = useState(false);
const [recipes, setRecipes] = useState([]);
Expand All @@ -29,7 +31,28 @@ const Dashboard = () => {
};
const [viewingState, setViewingState] = useState(ViewState.RECIPE);
const inputFile = useRef(null); // for redirecting click to open input file

useEffect(() => {
let token = localStorage.getItem("tastytoken");
if (token) {
token = JSON.parse(token);
axios
.get(`${backendURL}/api/token`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
if (res.data.success) {
setUserData(res.data);
}
})
.catch((err) => {
console.log(err);
});
} else {
setUserData(null);
}
}, [path]);
// form to send image change request
const [form, setForm] = useState({
id: user._id,
Expand Down Expand Up @@ -153,7 +176,7 @@ const Dashboard = () => {
setError("User data is not available.");
}
}, [user._id]);

console.log(user)
const handleDelete = (id) => {
const val = confirm("Are you sure you want to delete this recipe?");
if (val) {
Expand Down Expand Up @@ -371,10 +394,13 @@ const Dashboard = () => {
<h1>
{user.firstName} {user.lastName}
</h1>
{userData && (

<h1 className="text-black">
Followers: {user.followers.length} Following:{" "}
{user.following.length}
Followers: {userData.user.followers.length} Following:{" "}
{userData.user.following.length}
</h1>
)}
{/*
<p className="mb-8 leading-relaxed">
Meggings kinfolk echo park stumptown DIY, kale chips beard
Expand Down
48 changes: 41 additions & 7 deletions frontend/src/Pages/Profile.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useState, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import { useParams, useLocation } 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 [user, setUser] = useState(null)
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")
Expand All @@ -18,6 +18,30 @@ export default function UserProfile() {
const [activeTab, setActiveTab] = useState('recipes')
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const path = useLocation().pathname;
useEffect(() => {
let token = localStorage.getItem("tastytoken");
if (token) {
token = JSON.parse(token);
axios
.get(`${backendURL}/api/token`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
if (res.data.success) {
setUser(res.data);
}
})
.catch((err) => {
console.log(err);
});
} else {
setUser(null);
}
}, [path]);


useEffect(() => {
// Fetch user information
Expand All @@ -34,6 +58,8 @@ export default function UserProfile() {
setImagePreview(res.data.profile)
setFollowingCount(res.data.following.length)
setFollowers(res.data.followers.length)
console.log(user)
setFollowing(res.data.followers.includes(user.user._id))
})
.catch((err) => {
console.error("Error fetching user data", err)
Expand Down Expand Up @@ -82,12 +108,20 @@ export default function UserProfile() {
fetchUserImage()
fetchRecipes()
fetchLikedRecipes() // Call the fetchLikedRecipes function to get liked recipes
}, [id, backendURL, token]) // Use id, backendURL, and token in dependencies
}, [id, backendURL, token, user]) // Use id, backendURL, and token in dependencies

const handleFollow = () => {
setFollowing(!following)
setFollowers(followers + (following ? -1 : 1))
}
const handleFollow = async () => {
try {
await axios.post(`${backendURL}/api/follow`,
{ username: JSON.parse(localStorage.getItem("username")), userId: id },
{ headers: { Authorization: `Bearer ${token}` }}
);
setFollowing(!following);
setFollowers(followers + (following ? -1 : 1));
} catch (err) {
console.error("Error updating follow status", err);
}
};

return (
<div className="bg-white min-h-screen">
Expand Down

0 comments on commit 2edca11

Please sign in to comment.