diff --git a/client/src/App.js b/client/src/App.js
index 46f1393..3672d84 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -28,7 +28,7 @@ function App() {
-
+
>
)
}
diff --git a/client/src/components/PostItem.jsx b/client/src/components/PostItem.jsx
index bb22bd0..40167b7 100644
--- a/client/src/components/PostItem.jsx
+++ b/client/src/components/PostItem.jsx
@@ -1,10 +1,21 @@
-const PostItem = ({ post }) => {
+import { FaRegEdit, FaTrash } from 'react-icons/fa'
+
+const PostItem = (props) => {
+ const { post, deletePostAction } = {...props}
return (
-
{post.title}
+
{props.post.title}
{post.content}
+
+
+
+
)
}
diff --git a/client/src/features/blog/blogService.js b/client/src/features/blog/blogService.js
index 78826f4..5bf053e 100644
--- a/client/src/features/blog/blogService.js
+++ b/client/src/features/blog/blogService.js
@@ -1,6 +1,6 @@
import axios from 'axios'
-const API_URL = 'http://localhost:8000/blog'
+const API_URL = 'http://localhost:8000/blog/'
// Create new post
const createBlog = async (postData, token) => {
@@ -27,9 +27,22 @@ const getPosts = async (token) => {
return response.data
}
+// Delete a post
+const deletePost = async (token, postId) => {
+ const config = {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+
+ const response = await axios.delete(API_URL + postId, config)
+ return response.data
+}
+
const blogService = {
createBlog,
getPosts,
+ deletePost
}
export default blogService
diff --git a/client/src/features/blog/blogSlice.js b/client/src/features/blog/blogSlice.js
index 85741c0..088ba0b 100644
--- a/client/src/features/blog/blogSlice.js
+++ b/client/src/features/blog/blogSlice.js
@@ -1,5 +1,6 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import blogService from './blogService'
+import { toast } from "react-toastify";
const initialState = {
posts: [],
@@ -50,6 +51,28 @@ export const getPosts = createAsyncThunk(
}
)
+// Delete single user post
+export const deletePost = createAsyncThunk(
+ 'blog/delete',
+ async (postId, thunkAPI) => {
+ try {
+ const token = thunkAPI.getState().auth.user.access_token
+ await blogService.deletePost(token, postId)
+ toast.success('Deleted post successfully')
+ thunkAPI.dispatch(getPosts());
+ } catch (error) {
+ const message =
+ (error.response &&
+ error.response.data &&
+ error.response.data.message) ||
+ error.message ||
+ error.toString()
+
+ return thunkAPI.rejectWithValue(message)
+ }
+ }
+)
+
export const postSlice = createSlice({
name: 'post',
initialState,
@@ -83,6 +106,18 @@ export const postSlice = createSlice({
state.isError = true
state.message = action.payload
})
+ .addCase(deletePost.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(deletePost.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.isSuccess = true
+ })
+ .addCase(deletePost.rejected, (state, action) => {
+ state.isLoading = false
+ state.isError = true
+ state.message = action.payload
+ })
},
})
diff --git a/client/src/index.css b/client/src/index.css
index 7a426c5..7b23b00 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -359,3 +359,13 @@ footer {
font-size: 1.5rem;
}
}
+
+.action-buttons {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.action-buttons button {
+ margin: auto 0.5rem;
+}
diff --git a/client/src/pages/Posts.jsx b/client/src/pages/Posts.jsx
index d7e9a00..df44c66 100644
--- a/client/src/pages/Posts.jsx
+++ b/client/src/pages/Posts.jsx
@@ -1,50 +1,68 @@
-import { useEffect } from 'react'
-import { useSelector, useDispatch } from 'react-redux'
-import { getPosts, reset } from '../features/blog/blogSlice'
-import Spinner from '../components/Spinner'
-import BackButton from '../components/BackButton'
-import PostItem from '../components/PostItem'
+import { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { toast } from "react-toastify";
+import { getPosts, deletePost, reset } from "../features/blog/blogSlice";
+import Spinner from "../components/Spinner";
+import BackButton from "../components/BackButton";
+import PostItem from "../components/PostItem";
const Posts = () => {
- const { posts, isLoading, isSuccess } = useSelector(
+ const { posts, isLoading, isError, isSuccess, message } = useSelector(
(state) => state.blog
- )
+ );
- const dispatch = useDispatch()
+ const dispatch = useDispatch();
useEffect(() => {
return () => {
if (isSuccess) {
- dispatch(reset())
+ dispatch(reset());
}
- }
- }, [dispatch, isSuccess])
+ };
+ }, [dispatch, isSuccess]);
+
+ const deletePostAction = (postId) => {
+ dispatch(deletePost(postId));
+ };
+
+ if (isError) {
+ toast.error(message);
+ }
useEffect(() => {
- dispatch(getPosts())
- }, [dispatch])
+ dispatch(getPosts());
+ }, [dispatch]);
if (isLoading) {
- return
+ return ;
}
return (
<>
-
+
Posts
-
-
-
Title
-
Content
+ {posts.length === 0 ? (
+
No posts found
+ ) : (
+
+
+
Title
+
Content
+
Actions
+
+ {posts.map((post) => (
+
+ ))}
- {posts.map((post) => (
-
- ))}
-
+ )}
>
- )
-}
+ );
+};
-export default Posts
+export default Posts;