Skip to content

Commit

Permalink
UserPage added with delete post functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
burakorkmez committed Aug 24, 2023
1 parent b3126d2 commit a0518ee
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 16 deletions.
23 changes: 22 additions & 1 deletion backend/controllers/postController.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ const deletePost = async (req, res) => {
return res.status(401).json({ error: "Unauthorized to delete post" });
}

if (post.img) {
const imgId = post.img.split("/").pop().split(".")[0];
await cloudinary.uploader.destroy(imgId);
}

await Post.findByIdAndDelete(req.params.id);

res.status(200).json({ message: "Post deleted successfully" });
Expand Down Expand Up @@ -147,4 +152,20 @@ const getFeedPosts = async (req, res) => {
}
};

export { createPost, getPost, deletePost, likeUnlikePost, replyToPost, getFeedPosts };
const getUserPosts = async (req, res) => {
const { username } = req.params;
try {
const user = await User.findOne({ username });
if (!user) {
return res.status(404).json({ error: "User not found" });
}

const posts = await Post.find({ postedBy: user._id }).sort({ createdAt: -1 });

res.status(200).json(posts);
} catch (error) {
res.status(500).json({ error: error.message });
}
};

export { createPost, getPost, deletePost, likeUnlikePost, replyToPost, getFeedPosts, getUserPosts };
2 changes: 2 additions & 0 deletions backend/routes/postRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {
likeUnlikePost,
replyToPost,
getFeedPosts,
getUserPosts,
} from "../controllers/postController.js";
import protectRoute from "../middlewares/protectRoute.js";

const router = express.Router();

router.get("/feed", protectRoute, getFeedPosts);
router.get("/:id", getPost);
router.get("/user/:username", getUserPosts);
router.post("/create", protectRoute, createPost);
router.delete("/:id", protectRoute, deletePost);
router.put("/like/:id", protectRoute, likeUnlikePost);
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/components/Post.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import Actions from "./Actions";
import { useEffect, useState } from "react";
import useShowToast from "../hooks/useShowToast";
import { formatDistanceToNow } from "date-fns";
import { DeleteIcon } from "@chakra-ui/icons";
import { useRecoilValue } from "recoil";
import userAtom from "../atoms/userAtom";

const Post = ({ post, postedBy }) => {
const [user, setUser] = useState(null);
const showToast = useShowToast();
const currentUser = useRecoilValue(userAtom);

const navigate = useNavigate();

Expand All @@ -32,6 +36,25 @@ const Post = ({ post, postedBy }) => {
getUser();
}, [postedBy, showToast]);

const handleDeletePost = async (e) => {
try {
e.preventDefault();
if (!window.confirm("Are you sure you want to delete this post?")) return;

const res = await fetch(`/api/posts/${post._id}`, {
method: "DELETE",
});
const data = await res.json();
if (data.error) {
showToast("Error", data.error, "error");
return;
}
showToast("Success", "Post deleted", "success");
} catch (error) {
showToast("Error", error.message, "error");
}
};

if (!user) return null;
return (
<Link to={`/${user.username}/post/${post._id}`}>
Expand Down Expand Up @@ -105,6 +128,8 @@ const Post = ({ post, postedBy }) => {
<Text fontSize={"xs"} width={36} textAlign={"right"} color={"gray.light"}>
{formatDistanceToNow(new Date(post.createdAt))} ago
</Text>

{currentUser?._id === user._id && <DeleteIcon size={20} onClick={handleDeletePost} />}
</Flex>
</Flex>

Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/UserHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import useShowToast from "../hooks/useShowToast";
const UserHeader = ({ user }) => {
const toast = useToast();
const currentUser = useRecoilValue(userAtom); // logged in user
const [following, setFollowing] = useState(user.followers.includes(currentUser._id));
const [following, setFollowing] = useState(user.followers.includes(currentUser?._id));
const showToast = useShowToast();
const [updating, setUpdating] = useState(false);

Expand Down Expand Up @@ -57,7 +57,7 @@ const UserHeader = ({ user }) => {
user.followers.pop(); // simulate removing from followers
} else {
showToast("Success", `Followed ${user.name}`, "success");
user.followers.push(currentUser._id); // simulate adding to followers
user.followers.push(currentUser?._id); // simulate adding to followers
}
setFollowing(!following);

Expand Down Expand Up @@ -109,12 +109,12 @@ const UserHeader = ({ user }) => {

<Text>{user.bio}</Text>

{currentUser._id === user._id && (
{currentUser?._id === user._id && (
<Link as={RouterLink} to='/update'>
<Button size={"sm"}>Update Profile</Button>
</Link>
)}
{currentUser._id !== user._id && (
{currentUser?._id !== user._id && (
<Button size={"sm"} onClick={handleFollowUnfollow} isLoading={updating}>
{following ? "Unfollow" : "Follow"}
</Button>
Expand Down
42 changes: 31 additions & 11 deletions frontend/src/pages/UserPage.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { useEffect, useState } from "react";
import UserHeader from "../components/UserHeader";
import UserPost from "../components/UserPost";
import { useParams } from "react-router-dom";
import useShowToast from "../hooks/useShowToast";
import { Flex, Spinner } from "@chakra-ui/react";
import Post from "../components/Post";

const UserPage = () => {
const [user, setUser] = useState(null);
const { username } = useParams();
const showToast = useShowToast();
const [loading, setLoading] = useState(true);
const [posts, setPosts] = useState([]);
const [fetchingPosts, setFetchingPosts] = useState(true);

useEffect(() => {
const getUser = async () => {
Expand All @@ -22,13 +24,29 @@ const UserPage = () => {
}
setUser(data);
} catch (error) {
showToast("Error", error, "error");
showToast("Error", error.message, "error");
} finally {
setLoading(false);
}
};

const getPosts = async () => {
setFetchingPosts(true);
try {
const res = await fetch(`/api/posts/user/${username}`);
const data = await res.json();
console.log(data);
setPosts(data);
} catch (error) {
showToast("Error", error.message, "error");
setPosts([]);
} finally {
setFetchingPosts(false);
}
};

getUser();
getPosts();
}, [username, showToast]);

if (!user && loading) {
Expand All @@ -43,15 +61,17 @@ const UserPage = () => {
return (
<>
<UserHeader user={user} />
<UserPost likes={1200} replies={481} postImg='/post1.png' postTitle="Let's talk about threads." />
<UserPost likes={451} replies={12} postImg='/post2.png' postTitle='Nice tutorial. Highly recommended.' />
<UserPost
likes={6721}
replies={989}
postImg='/post3.png'
postTitle="I love this guy and can't wait to see him in cage. 💪"
/>
<UserPost likes={212} replies={56} postTitle='This is my first thread.' />

{!fetchingPosts && posts.length === 0 && <h1>User has not posts.</h1>}
{fetchingPosts && (
<Flex justifyContent={"center"} my={12}>
<Spinner size={"xl"} />
</Flex>
)}

{posts.map((post) => (
<Post key={post._id} post={post} postedBy={post.postedBy} />
))}
</>
);
};
Expand Down

0 comments on commit a0518ee

Please sign in to comment.