diff --git a/Startup-app/backend/routes/ideaRoutes.js b/Startup-app/backend/routes/ideaRoutes.js index a54becb2fdf36ad2e9bef662d020d84350f13e3c..cc0f0ec3d355517ee3ffc3187916ee10f70df7c6 100644 --- a/Startup-app/backend/routes/ideaRoutes.js +++ b/Startup-app/backend/routes/ideaRoutes.js @@ -1,4 +1,5 @@ const express = require('express'); +const { toggleCollaboration, getCollaborators } = require('../controllers/ideaController'); const router = express.Router(); const auth = require('../middleware/auth'); const multer = require('multer'); @@ -81,13 +82,14 @@ router.get('/feed', auth, async (req, res) => { const currentUserId = req.user.id; const currentUser = await User.findById(currentUserId).select('following'); - const ideas = await Idea.find().sort({ createdAt: -1 }); + const ideas = await Idea.find().populate('collaborators', '_id').sort({ createdAt: -1 }); const followedIds = currentUser?.following?.map(id => id.toString()) || []; const ideasWithFollowStatus = ideas.map(idea => ({ ...idea.toObject(), - followed: followedIds.includes(idea.userId.toString()) + followed: followedIds.includes(idea.userId.toString()), + collaborators: idea.collaborators.map(c => c._id.toString()) })); res.status(200).json(ideasWithFollowStatus); @@ -97,4 +99,20 @@ router.get('/feed', auth, async (req, res) => { } }); +router.post('/collaborate', auth, toggleCollaboration); +router.get('/:ideaId/collaborators', auth, getCollaborators); + +router.put('/:ideaId/revert-collab', async (req, res) => { + const { userId } = req.body; + const idea = await Idea.findById(req.params.ideaId); + if (!idea) return res.status(404).send('Idea not found'); + + idea.collaborators = idea.collaborators.filter( + id => id.toString() !== userId + ); + + await idea.save(); + res.status(200).json({ message: 'Collaboration reverted' }); +}); + module.exports = router; \ No newline at end of file diff --git a/Startup-app/frontend/src/pages/Feed.js b/Startup-app/frontend/src/pages/Feed.js index d1c03cbcee8978f9de0239eb5b8160ebf59d7aa1..5a6d2921292b799085489275b848eece29535e1d 100644 --- a/Startup-app/frontend/src/pages/Feed.js +++ b/Startup-app/frontend/src/pages/Feed.js @@ -51,6 +51,62 @@ const Feed = () => { } }; + const handleCollaboration = async (ideaId) => { + if (!currentUserId) return; + try { + const currentIdea = ideas.find((idea) => idea._id === ideaId); + const wasCollaborating = currentIdea.collaborators.includes(currentUserId); + const response = await axios.post( + 'http://localhost:5001/api/ideas/collaborate', + { ideaId }, + { headers: { Authorization: `Bearer ${token}` } } + ); + setIdeas((prev) => + prev.map((idea) => + idea._id === ideaId + ? { ...idea, collaborators: response.data.collaborators } + : idea + ) + ); + const isCollaborating = response.data.collaborators.includes(currentUserId); + setMessage( + wasCollaborating + ? 'Collaboration reverted successfully!' + : 'Collaboration request sent successfully!' + ); + } catch (error) { + console.error('Collaboration error:', error.response?.data || error.message); + setMessage('Failed to update collaboration status.'); + } + }; + + const handleRevertCollab = async (ideaId) => { + if (!currentUserId) return; + + try { + await axios.put(`http://localhost:5001/api/ideas/${ideaId}/revert-collab`, { + userId: currentUserId + }); + + // Update state after removing collaborator + setIdeas(prevIdeas => + prevIdeas.map(idea => + idea._id === ideaId + ? { + ...idea, + collaborators: idea.collaborators.filter(id => id !== currentUserId) + } + : idea + ) + ); + + setMessage('Collaboration reverted successfully!'); + } catch (error) { + console.error('Error reverting collaboration:', error); + setMessage('Error reverting collaboration.'); + } + }; + const handleFollow = async (userId) => { if (!userId || userId === currentUserId) return; @@ -126,6 +182,7 @@ const Feed = () => { ...idea, followed: serverFollowing.includes(idea.userId), likedBy: idea.likedBy || [], + collaborators: idea.collaborators || [] })); const filteredIdeas = selectedDomain @@ -186,15 +243,30 @@ const Feed = () => { {idea.userId === currentUserId ? ( <span className="posted-by-you">Posted by You</span> ) : ( - <button - className={`follow-btn ${idea.followed ? 'followed' : ''}`} - onClick={(e) => { - e.stopPropagation(); - idea.followed ? handleUnfollow(idea.userId) : handleFollow(idea.userId); - }} - > - {idea.followed ? 'Unfollow' : 'Follow'} - </button> + <> + <div className="button-group"> + <button + className="collaborate-btn" + onClick={(e) => { + e.stopPropagation(); + idea.collaborators.includes(currentUserId) ? handleRevertCollab(idea._id) : handleCollaboration(idea._id); + } } + > + {idea.collaborators.includes(currentUserId) + ? 'Revert Collab' + : 'Collaborate'} + </button> + + <button + className={`follow-btn ${idea.followed ? 'followed' : ''}`} + onClick={(e) => { + e.stopPropagation(); + idea.followed ? handleUnfollow(idea.userId) : handleFollow(idea.userId); + } } + > + {idea.followed ? 'Unfollow' : 'Follow'} + </button> + </div></> )} </div> diff --git a/Startup-app/frontend/src/styles/Feed.css b/Startup-app/frontend/src/styles/Feed.css index 32157f529202b1d6b6198d88d4028e94027378a6..ee81f1dc656bffc1b1c775ea4baaa06c35099b3c 100644 --- a/Startup-app/frontend/src/styles/Feed.css +++ b/Startup-app/frontend/src/styles/Feed.css @@ -402,4 +402,31 @@ border-radius: 20px; font-size: 0.85rem; font-weight: 500; +} + +.collaborate-btn, .collaborators-btn { + background-color: #2c7be5; + color: white; + border: none; + padding: 6px 10px; + height: 30px; + font-size: 0.8rem; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.2s ease; + white-space: nowrap; + width: 130px; + text-align: center; + margin-right: 10px; +} + +.collaborate-btn:hover, .collaborators-btn:hover { + background-color: #0056b3; +} + +.button-group { + display: flex; + justify-content: space-between; + margin-top: 10px; + gap: 10px; } \ No newline at end of file diff --git a/Startup-app/frontend/src/styles/MyPosts.css b/Startup-app/frontend/src/styles/MyPosts.css index 868fea198652299062a88ae76fe9264c07df9335..0e04906010cbe11122243d01b081a5d7e421e882 100644 --- a/Startup-app/frontend/src/styles/MyPosts.css +++ b/Startup-app/frontend/src/styles/MyPosts.css @@ -58,4 +58,24 @@ .create-first-button:hover { background-color: #45a049; + } + + .collaborate-btn, .collaborators-btn { + background-color: #2c7be5; + color: white; + border: none; + padding: 6px 10px; + height: 30px; + font-size: 0.8rem; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.2s ease; + white-space: nowrap; + width: 150px; + margin-right: 10px; + text-align: center; + } + + .collaborate-btn:hover, .collaborators-btn:hover { + background-color: #0056b3; } \ No newline at end of file