Skip to content

Commit

Permalink
added-follow-list (#446)
Browse files Browse the repository at this point in the history
  • Loading branch information
IkkiOcean authored Nov 10, 2024
1 parent c71813b commit 91a82be
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 15 deletions.
44 changes: 44 additions & 0 deletions backend/Controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,55 @@ const toggleFollowUser = async (req, res) => {




import mongoose from "mongoose";

const getFollowerAndFollowingList = async (req, res) => {
const { id } = req.params; // Get the user ID from route params

// Check if the user ID is valid (mongoose checks for ObjectId format)
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({ message: "Invalid user ID" });
}

try {
// Find the user with the provided ID
const user = await User.findById(id);

if (!user) {
return res.status(404).json({ message: "User not found" });
}

// Fetch the followers' details
const followers = await User.find({ '_id': { $in: user.followers } })
.select('firstName lastName username profile'); // Only select necessary fields

// Fetch the following details
const following = await User.find({ '_id': { $in: user.following } })
.select('firstName lastName username profile'); // Only select necessary fields

// Return the followers and following data
return res.json({
followers,
following,
});
} catch (err) {
console.error("Error fetching followers and following", err);
return res.status(500).json({ message: "Server error" });
}
};

export { getFollowerAndFollowingList };




const UserController = {
Signup,
Login,
getAllUserName,
toggleFollowUser,
getFollowerAndFollowingList,
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 @@ -21,6 +21,7 @@ router.get("/verify-account", VerificationController.verifyEmail);
router.post("/reverify-account", VerificationController.resendVerificationEmail);

router.post("/login", UserController.Login);
router.get("/user/:id/followers-following", UserController.getFollowerAndFollowingList);
router.post("/submitFeedback", UserController.submitFeedback);
router.post("/follow", UserController.toggleFollowUser);
router.get('/feedback', UserController.getAllFeedback);
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/Components/FollowerModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// FollowModal.js
import React from 'react';

export default function FollowModal({ isOpen, onClose, followers, following, activeTab, setActiveTab }) {
console.log(following)
if (!isOpen) return null;

return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg max-w-md w-full p-4">
<div className="flex justify-between mb-4">
<h2 className="text-xl font-semibold">Followers & Following</h2>
<button onClick={onClose} className="text-gray-500 hover:text-red-500">&times;</button>
</div>

{/* Tab Header */}
<div className="flex border-b border-gray-200 mb-4">
<button
className={`w-1/2 py-2 text-center ${activeTab === 'followers' ? 'border-b-2 border-red-700 text-red-700' : 'text-gray-500'}`}
onClick={() => setActiveTab('followers')}
>
Followers
</button>
<button
className={`w-1/2 py-2 text-center ${activeTab === 'following' ? 'border-b-2 border-red-700 text-red-700' : 'text-gray-500'}`}
onClick={() => setActiveTab('following')}
>
Following
</button>
</div>

{/* Tab Content */}
<div className="h-64 overflow-y-auto">
{activeTab === 'followers' ? (
followers.length > 0 ? (
followers.map((follower) => (
<div key={follower._id} className="flex items-center mb-2">
<img src={follower.profile || "/placeholder.svg"} alt={follower.username} className="w-10 h-10 rounded-full mr-3" />
<div>
<span class="block text-red-700">@{follower.username}</span>
<span class="block text-sm">{follower.firstName} {follower.lastName}</span>
</div>
</div>
))
) : (
<p className="text-gray-500">No followers found.</p>
)
) : (
following.length > 0 ? (
following.map((followedUser) => (
<div key={followedUser._id} className="flex items-center mb-2">
<img src={followedUser.profile || "/placeholder.svg"} alt={followedUser.username} className="w-10 h-10 rounded-full mr-3" />
<div>
<span class="block text-red-700">@{followedUser.username}</span>
<span class="block text-sm">{followedUser.firstName} {followedUser.lastName}</span>
</div>
</div>
))
) : (
<p className="text-gray-500">No following users found.</p>
)
)}
</div>
</div>
</div>
);
}
74 changes: 59 additions & 15 deletions frontend/src/Pages/Profile.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { useParams, useLocation } from 'react-router-dom'

import FollowModal from '../Components/FollowerModal'
import axios from 'axios'

export default function UserProfile() {
Expand All @@ -9,7 +9,8 @@ export default function UserProfile() {
const token = JSON.parse(localStorage.getItem("tastytoken")) // Token still comes from local storage for authentication

const [user, setUser] = useState(null)

const [followingList, setFollowingList] = useState(null)
const [followersList, setFollowersList] = 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 Down Expand Up @@ -48,6 +49,7 @@ export default function UserProfile() {


useEffect(() => {
if (user) {
// Fetch user information
const fetchUserImage = () => {
axios
Expand Down Expand Up @@ -113,8 +115,8 @@ export default function UserProfile() {
fetchUserImage()
fetchRecipes()
fetchLikedRecipes() // Call the fetchLikedRecipes function to get liked recipes

}, [id, backendURL, token, user]) // Use id, backendURL, and token in dependencies
}
}, [user])

const handleFollow = async () => {
try {
Expand All @@ -128,8 +130,34 @@ export default function UserProfile() {
console.error("Error updating follow status", err);
}
};
useEffect(() => {
if(user){
const fetchFollowersFollowing = async () => {
try {
const response = await axios.get(`${backendURL}/api/user/${id}/followers-following`);
setFollowersList(response.data.followers);
setFollowingList(response.data.following);
console.log(response)
setLoading(false);
} catch (err) {
setError("Error fetching data");
setLoading(false);
}
};

fetchFollowersFollowing();
}
}, [user]);

const [isModalOpen, setIsModalOpen] = useState(false);
const [activeModalTab, setActiveModalTab] = useState('followers'); // Tracks which tab to show in modal

const handleOpenModal = (tab) => {
setActiveModalTab(tab);
setIsModalOpen(true);
};

const handleCloseModal = () => setIsModalOpen(false);
return (
<div className="bg-white min-h-screen">
{/* Banner and Profile Picture */}
Expand All @@ -155,23 +183,31 @@ export default function UserProfile() {
<h1 className="text-2xl font-bold">{username}</h1>
<p className="text-gray-600 mt-1">{bio}</p>
</div>
{(user && (user.user._id !== id)) &&
<button
className={`px-4 py-2 rounded-full ${
following
? 'bg-white text-red-700 border border-red-700 hover:bg-red-50'
: 'bg-red-700 text-white hover:bg-red-800'
}`}
onClick={handleFollow}
>
{following ? 'Following' : 'Follow'}
</button>
className={`px-4 py-2 rounded-full ${
following
? 'bg-white text-red-700 border border-red-700 hover:bg-red-50'
: 'bg-red-700 text-white hover:bg-red-800'
}`}
onClick={handleFollow}
>
{following ? 'Following' : 'Follow'}
</button>}

</div>

{/* User Stats */}
<div className="flex gap-4 mt-4 text-sm">
<span><strong>{recipes.length}</strong> Recipes</span>
<span><strong>{followers}</strong> Followers</span>
<span><strong>{followingCount}</strong> Following</span>

<button onClick={() => handleOpenModal('followers')}>
<strong>{followers}</strong> Followers
</button>
<button onClick={() => handleOpenModal('following')}>
<strong>{followingCount}</strong> Following
</button>

</div>
</div>

Expand Down Expand Up @@ -252,6 +288,14 @@ export default function UserProfile() {
</div>
)}
</div>
<FollowModal
isOpen={isModalOpen}
onClose={handleCloseModal}
followers={followersList} // Replace with actual followers data
following={followingList} // Replace with actual following data
activeTab={activeModalTab}
setActiveTab={setActiveModalTab}
/>
</div>
)
}

0 comments on commit 91a82be

Please sign in to comment.