import React, { useState, useEffect, useContext, useCallback } from "react"; import axios from "axios"; import { toast } from "react-toastify"; import { AuthContext } from "../context/AuthContext"; import { SocketContext } from "../context/SocketContext"; /** * SocialFeed component displays community posts and allows creating new posts * Includes real-time updates via Socket.IO */ const SocialFeed = () => { const { auth } = useContext(AuthContext); const { socket, connected, on, off } = useContext(SocketContext); const [posts, setPosts] = useState([]); const [content, setContent] = useState(""); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [submitting, setSubmitting] = useState(false); const [likingPostId, setLikingPostId] = useState(null); // Load posts from API const loadPosts = useCallback(async () => { try { setLoading(true); setError(null); const res = await axios.get("/api/posts"); setPosts(res.data); } catch (err) { console.error("Error loading posts:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to load posts. Please try again later."; setError(errorMessage); toast.error(errorMessage); } finally { setLoading(false); } }, []); useEffect(() => { loadPosts(); }, [loadPosts]); // Handle real-time post updates via Socket.IO useEffect(() => { if (!socket || !connected) return; const handleNewPost = (data) => { console.log("Received new post:", data); setPosts((prevPosts) => [data.post, ...prevPosts]); toast.info("New post added to feed!"); }; const handlePostUpdate = (data) => { console.log("Received post update:", data); if (data.type === "post_liked") { // Update specific post likes setPosts((prevPosts) => prevPosts.map((post) => post._id === data.postId ? { ...post, likes: data.likes } : post ) ); } else if (data.type === "post_updated") { // Update existing post setPosts((prevPosts) => prevPosts.map((post) => post._id === data.post._id ? data.post : post ) ); } else if (data.type === "post_deleted") { // Remove deleted post setPosts((prevPosts) => prevPosts.filter((post) => post._id !== data.postId) ); } }; const handleNewComment = (data) => { console.log("Received new comment:", data); // Update post with new comment setPosts((prevPosts) => prevPosts.map((post) => post._id === data.postId ? { ...post, comments: [...(post.comments || []), data.comment] } : post ) ); }; // Subscribe to post events on("newPost", handleNewPost); on("postUpdate", handlePostUpdate); on("newComment", handleNewComment); // Cleanup on unmount return () => { off("newPost", handleNewPost); off("postUpdate", handlePostUpdate); off("newComment", handleNewComment); }; }, [socket, connected, on, off]); // Like a post const likePost = async (id) => { if (!auth.isAuthenticated) { toast.warning("Please login to like posts"); return; } try { setLikingPostId(id); const token = localStorage.getItem("token"); const res = await axios.put( `/api/posts/like/${id}`, {}, { headers: { "x-auth-token": token, }, } ); setPosts( posts.map((post) => post._id === id ? { ...post, likes: res.data } : post ) ); } catch (err) { console.error("Error liking post:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to like post. Please try again."; toast.error(errorMessage); } finally { setLikingPostId(null); } }; // Submit a new post const onSubmit = async (e) => { e.preventDefault(); if (!auth.isAuthenticated) { toast.warning("Please login to create posts"); return; } if (!content.trim()) { toast.warning("Post content cannot be empty"); return; } try { setSubmitting(true); const token = localStorage.getItem("token"); const res = await axios.post( "/api/posts", { content }, { headers: { "x-auth-token": token, }, } ); setPosts([res.data, ...posts]); setContent(""); toast.success("Post created successfully!"); } catch (err) { console.error("Error creating post:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to create post. Please try again."; toast.error(errorMessage); } finally { setSubmitting(false); } }; if (loading) { return (
Loading...

Loading posts...

); } if (error) { return (

Error Loading Posts

{error}


); } return (

Social Feed

{connected && ( Live Updates )}
{auth.isAuthenticated && (
Create a Post