Skip to content

Commit

Permalink
Merge pull request #140 from MeetDOD/issue-126
Browse files Browse the repository at this point in the history
feat: Added deleting a post created by a user successfully Issue 126
  • Loading branch information
VaibhavArora314 authored Jun 8, 2024
2 parents 8d49b73 + e167952 commit e22702c
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 11 deletions.
42 changes: 42 additions & 0 deletions backend/src/routes/post/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,45 @@ export const getLeaderboardController = async (req: Request, res: Response) => {
});
}
};

export const deletePostController = async (req: UserAuthRequest, res: Response) => {
try {
const userId = req.userId;
const postId = req.params.id;

if (!userId) {
return res.status(403).json({ error: { message: "Invalid user" } });
}

const post = await prisma.post.findUnique({
where: { id: postId },
});

if (!post) {
return res.status(404).json({ error: { message: "Post not found" } });
}

if (post.authorId !== userId) {
return res.status(403).json({ error: { message: "You are not authorized to delete this post" } });
}

await prisma.userPostInteraction.deleteMany({
where: { postId }
});
await prisma.comment.deleteMany({
where: { postId }
});
await prisma.favorite.deleteMany({
where: { postId }
});

await prisma.post.delete({
where: { id: postId },
});

res.status(200).json({ message: "Post deleted successfully" });
} catch (error) {
console.log(error)
res.status(500).json({ error: { message: "An unexpected error occurred" } });
}
};
4 changes: 3 additions & 1 deletion backend/src/routes/post/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import { Router } from "express";
import authMiddleware from "../../middleware/auth"
import { createCommentController, createPostController, dislikePostController, favoritePostController, getCommentsController, getFavoritePostsController, getLeaderboardController, getPostController, getPostsWithPagination, likePostController, unfavoritePostController } from "./controller";
import { createCommentController, createPostController, deletePostController, dislikePostController, favoritePostController, getCommentsController, getFavoritePostsController, getLeaderboardController, getPostController, getPostsWithPagination, likePostController, unfavoritePostController } from "./controller";

const postRouter = Router();

Expand Down Expand Up @@ -29,4 +29,6 @@ postRouter.get('/:id/favorites', authMiddleware, getFavoritePostsController);

postRouter.get('/all/leaderboard', getLeaderboardController);

postRouter.delete('/delete/:id', authMiddleware, deletePostController);

export default postRouter;
49 changes: 46 additions & 3 deletions frontend/src/components/PostCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
import { Link } from "react-router-dom";
import { IPost } from "../types";
import { IPost, IUser } from "../types";
import { MdDeleteOutline } from "react-icons/md";
import axios from "axios";
import { useState } from "react";
import toast from "react-hot-toast";

type Props = {
post: IPost;
onDelete: (id: string) => void;
currentUser: IUser ;
};

const PostCard = ({ post }: Props) => {
const PostCard = ({ post,onDelete,currentUser }: Props) => {

const [isDeleting, setIsDeleting] = useState(false);

const handleDelete = async () => {
setIsDeleting(true);
try {
const token = localStorage.getItem('token');
if (!token) {
toast.error('Please login to remove a post from favorites');
return;
}
await axios.delete(`/api/v1/posts/delete/${post.id}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
onDelete(post.id);
toast.error('Post Deleted successfully !')
} catch (error) {
console.error("Failed to delete post", error);
} finally {
setIsDeleting(false);
}
};

return (
<div
key={post.id}
Expand All @@ -28,12 +59,24 @@ const PostCard = ({ post }: Props) => {
</span>
))}
</div>
<div className="flex justify-between mt-1">
<Link
to={`/app/posts/${post.id}`}
className="inline-block mt-4 text-blue-400 hover:text-blue-300 transition-colors duration-200"
className="inline-block mt-4 text-blue-400 hover:text-blue-300 transition-colors duration-200 rounded-3xl border-2 border-blue-500 hover:border-blue-300 px-4 py-2"
>
Read more
</Link>
{currentUser && currentUser.id === post.author.id && (
<button
onClick={handleDelete}
disabled={isDeleting}
className="justify-end ml-4 mt-4 inline-block text-red-500 hover:text-red-400 transition-colors duration-200 border-2 border-red-500 hover:border-red-400 p-2 rounded-3xl"
>
{isDeleting ? "Deleting..." : <MdDeleteOutline size={25} />}
</button>
)}
</div>

</div>
);
};
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/pages/Favorite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const Favorite = () => {
const [loading, setLoading] = useState(true);
const [errorMessage, setErrorMessage] = useState("");
const token = useRecoilValue(tokenState);
const currentUser = useRecoilValue(userState);

const fetchFavoritePosts = async (user: IUser): Promise<IPost[]> => {
try {
Expand Down Expand Up @@ -47,6 +48,11 @@ const Favorite = () => {
getFavoritePosts();
}, [user]);

const handleDelete = (id: string) => {
setFavoritePosts((prevPosts) => prevPosts.filter((post) => post.id !== id));
};


if (loading) {
return <Loader />;
}
Expand All @@ -67,7 +73,7 @@ const Favorite = () => {
<h4 className="font-semibold">Favorite Posts ( {favoritePosts.length} )</h4>
<div className="mt-6 mb-8 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">
{favoritePosts.map(post => (
<PostCard key={post.id} post={post} />
<PostCard key={post.id} post={post} onDelete={handleDelete} currentUser={currentUser}/>
))}
</div>
</>
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/pages/HomePagePosts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import axios from 'axios';
import { IPost } from '../types';
import Loader from '../components/Loader';
import PostCard from '../components/PostCard';
import { userState } from '../store/atoms/auth';
import { useRecoilValue } from 'recoil';

const HomePagePost = () => {
const [posts, setPosts] = useState<IPost[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const currentUser = useRecoilValue(userState);

useEffect(() => {
const fetchPosts = async () => {
Expand All @@ -25,6 +28,10 @@ const HomePagePost = () => {
fetchPosts();
}, []);

const handleDelete = (id: string) => {
setPosts((prevPosts) => prevPosts.filter((post) => post.id !== id));
};

if (loading) {
return <Loader />;
}
Expand All @@ -38,7 +45,7 @@ const HomePagePost = () => {
<h1 className="text-3xl font-semibold my-4 text-white">📃 Recent Posts Added</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full my-10">
{posts.map((post, index) => (
<PostCard key={index} post={post} />
<PostCard key={index} post={post} onDelete={handleDelete} currentUser={currentUser} />
))}
</div>
</div>
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/pages/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import axios from 'axios';
import { IPost } from '../types';
import Loader from '../components/Loader';
import PostCard from '../components/PostCard';
import { userState } from '../store/atoms/auth';
import { useRecoilValue } from 'recoil';

const Posts = () => {
const [posts, setPosts] = useState<IPost[]>([]);
Expand All @@ -16,6 +18,8 @@ const Posts = () => {
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);

const currentUser = useRecoilValue(userState);

useEffect(() => {
const fetchPosts = async () => {
try {
Expand Down Expand Up @@ -99,6 +103,10 @@ const Posts = () => {
return <div className='text-red-500 font-semibold text-lg text-center'>{error}</div>;
}

const handleDelete = (id: string) => {
setPosts((prevPosts) => prevPosts.filter((post) => post.id !== id));
};

return (
<div className='max-w-screen-xl flex flex-col items-center justify-center mx-auto p-4'>
<h1 className="text-2xl font-semibold mb-4 text-white">Posts</h1>
Expand Down Expand Up @@ -160,7 +168,7 @@ const Posts = () => {
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">
{filteredPosts.map((post, index) => (
<PostCard key={index} post={post} />
<PostCard key={index} post={post} onDelete={handleDelete} currentUser={currentUser} />
))}
</div>
<div className="flex justify-center items-center mt-4 w-full space-x-2">
Expand Down
14 changes: 10 additions & 4 deletions frontend/src/pages/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useEffect, useState } from "react";
import { IUser } from "../types";
import { IPost, IUser } from "../types";
import axios from "axios";
import { useRecoilValue } from "recoil";
import { tokenState } from "../store/atoms/auth";
import { tokenState, userState } from "../store/atoms/auth";
import Loader from "../components/Loader";
import PostCard from "../components/PostCard";
import { GoUnverified } from "react-icons/go";
Expand All @@ -12,13 +12,15 @@ import { AiTwotoneInfoCircle } from "react-icons/ai";
import toast from "react-hot-toast";

const Profile = () => {
const [posts, setPosts] = useState<IPost[]>([]);
const [user, setUser] = useState<IUser | null>(null);
const [loading, setLoading] = useState(true);
const [errorMessage, setErrorMessage] = useState("");
const [otpSent, setOtpSent] = useState(false);
const [otp, setOtp] = useState("");
const [verificationError, setVerificationError] = useState("");
const token = useRecoilValue(tokenState);
const currentUser = useRecoilValue(userState);

useEffect(() => {
const fetchUser = async () => {
Expand All @@ -37,7 +39,7 @@ const Profile = () => {
};

fetchUser();
}, [token]);
}, [token,posts]);

const handleGenerateOtp = async () => {
try {
Expand Down Expand Up @@ -79,6 +81,10 @@ const Profile = () => {
}
};

const handleDelete = (id: string) => {
setPosts((prevPosts) => prevPosts.filter((post) => post.id !== id));
};

if (loading) {
return <Loader />;
}
Expand Down Expand Up @@ -135,7 +141,7 @@ const Profile = () => {
<h4 className="font-semibold">Posts ( {user?.posts.length} )</h4>
<div className="mt-6 mb-8 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">

{user?.posts.map(post => <PostCard key={post.id} post={post} />)}
{user?.posts.map(post => <PostCard key={post.id} post={post} onDelete={handleDelete} currentUser={currentUser} />)}
</div>
</div>
</div>
Expand Down

0 comments on commit e22702c

Please sign in to comment.