Skip to content

Commit

Permalink
ui changes to the post page
Browse files Browse the repository at this point in the history
  • Loading branch information
Apfirebolt committed Aug 7, 2022
1 parent b0d6862 commit 3ec5de6
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 31 deletions.
2 changes: 1 addition & 1 deletion client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function App() {
</Routes>
</div>
</Router>
<ToastContainer />
<ToastContainer limit={1} />
</>
)
}
Expand Down
15 changes: 13 additions & 2 deletions client/src/components/PostItem.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
const PostItem = ({ post }) => {
import { FaRegEdit, FaTrash } from 'react-icons/fa'

const PostItem = (props) => {
const { post, deletePostAction } = {...props}
return (
<div className='post'>
<div>{post.title}</div>
<div>{props.post.title}</div>
<p>
{post.content}
</p>
<div className="action-buttons">
<button className="btn btn-danger">
<FaRegEdit /> Edit
</button>
<button className="btn" onClick={() => deletePostAction(props.post.id)}>
<FaTrash /> Delete
</button>
</div>
</div>
)
}
Expand Down
15 changes: 14 additions & 1 deletion client/src/features/blog/blogService.js
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -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
35 changes: 35 additions & 0 deletions client/src/features/blog/blogSlice.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import blogService from './blogService'
import { toast } from "react-toastify";

const initialState = {
posts: [],
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
})
},
})

Expand Down
10 changes: 10 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
72 changes: 45 additions & 27 deletions client/src/pages/Posts.jsx
Original file line number Diff line number Diff line change
@@ -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 <Spinner />
return <Spinner />;
}

return (
<>
<div className="section-heading">
<BackButton url='/' />
<BackButton url="/" />
<h1>Posts</h1>
</div>
<div className='posts'>
<div className='post-headings'>
<div>Title</div>
<div>Content</div>
{posts.length === 0 ? (
<p>No posts found</p>
) : (
<div className="posts">
<div className="post-headings">
<div>Title</div>
<div>Content</div>
<div>Actions</div>
</div>
{posts.map((post) => (
<PostItem
key={post.id}
post={post}
deletePostAction={deletePostAction}
/>
))}
</div>
{posts.map((post) => (
<PostItem key={post.id} post={post} />
))}
</div>
)}
</>
)
}
);
};

export default Posts
export default Posts;

0 comments on commit 3ec5de6

Please sign in to comment.