From 89f5c02aab0773a162f6fd9fb1429476aa65c266 Mon Sep 17 00:00:00 2001 From: JaberHPranto Date: Thu, 16 Sep 2021 20:32:41 +0600 Subject: [PATCH] getting all posts in frontend --- client/src/components/Blog/Blog.js | 35 ++++++++---- client/src/components/Blog/BlogCard.js | 21 ++++--- client/src/components/Blog/BlogDetails.js | 69 ++++++++++++++--------- client/src/constants/blogConstant.js | 5 ++ client/src/redux/actions/blogActions.js | 25 +++++++- client/src/redux/reducers/blogReducers.js | 18 +++++- client/src/store.js | 7 +-- server/controller/blogController.js | 11 ++++ server/routes/blogRoute.js | 5 +- 9 files changed, 140 insertions(+), 56 deletions(-) diff --git a/client/src/components/Blog/Blog.js b/client/src/components/Blog/Blog.js index 2afd944..d2b3dce 100644 --- a/client/src/components/Blog/Blog.js +++ b/client/src/components/Blog/Blog.js @@ -1,13 +1,24 @@ -import React from 'react' +import React, { useEffect } from 'react' import { Button, Col, Row } from 'react-bootstrap' +import { useDispatch, useSelector } from 'react-redux' import { useHistory } from 'react-router-dom' +import { fetchBlogs } from '../../redux/actions/blogActions' import '../../styles/blog.css' +import Loader from '../Ecommerce/Loader' import BlogCard from './BlogCard' import { blogCategories, blogTags } from './BlogSeedData' function Blog() { - const num = [1, 2, 3, 4, 5] + const history = useHistory() + const dispatch = useDispatch() + + const blogList = useSelector(state => state.blogList) + const { loading, blogs} = blogList + + useEffect(() => { + dispatch(fetchBlogs()) + }, [dispatch]) function handleCreateBlog(){ history.push("/newblog") @@ -44,15 +55,17 @@ function Blog() { - - - {num.map(n => ( - - - - ))} - - + {loading ? : ( + + + {blogs && blogs.map((blog,index) => ( + + + + ))} + + + )} diff --git a/client/src/components/Blog/BlogCard.js b/client/src/components/Blog/BlogCard.js index 2d3920c..ffaa177 100644 --- a/client/src/components/Blog/BlogCard.js +++ b/client/src/components/Blog/BlogCard.js @@ -1,26 +1,31 @@ import React from 'react' import { Badge, Button, Card } from 'react-bootstrap' +import { Link, useHistory } from 'react-router-dom' import "../../styles/blog.css" -function BlogCard() { - const tags = ['plant','indoor','gardening'] +function BlogCard({ blog }) { + const history = useHistory() + const handleViewBlog = (id) => { + history.push(`/blog/${id}`) + } return (
+ + + - How to plant - {tags.map((tag,index) => ( + {blog.title} + {blog.tags.map((tag,index) => ( {tag} ))} - Some quick example text to build on the card title and make up the bulk of - the card's content - Lorem ipsum, dolor sit amet consectetur adipisicing elit. A provident sint ipsam voluptate inventore deleniti, hic eligendi perspiciatis cum, rerum, facere sequi perferendis. Et temporibus, laboriosam velit quae quas non? + {blog.description}
- +
diff --git a/client/src/components/Blog/BlogDetails.js b/client/src/components/Blog/BlogDetails.js index ddfca4d..a18aff5 100644 --- a/client/src/components/Blog/BlogDetails.js +++ b/client/src/components/Blog/BlogDetails.js @@ -1,37 +1,50 @@ -import React from 'react' +import React, { useEffect } from 'react' import { Badge, Container } from 'react-bootstrap' +import { useDispatch, useSelector } from 'react-redux' +import { fetchBlogById } from '../../redux/actions/blogActions' import '../../styles/blog.css' +import Loader from '../Ecommerce/Loader' +import Message from '../Ecommerce/Message' -function BlogDetails() { - const tags = ['plant','indoor','gardening'] +function BlogDetails({match}) { + const dispatch = useDispatch() + const blogDetails = useSelector(state => state.blogDetails) + const { loading, blog, error } = blogDetails + useEffect(() => { + dispatch(fetchBlogById(match.params.id)) + }, [dispatch,match]) + return ( - blog hero -

A Plant’s Journey Home

-
-

By Jaber Hossain Pranto

-

Published in Plant

-

19 September,2021

-
-
- Lorem ipsum dolor, sit amet consectetur adipisicing elit. Iure vel officiis ipsum placeat itaque neque dolorem modi perspiciatis dolor distinctio veritatis sapiente, minima corrupti dolores necessitatibus suscipit accusantium dignissimos culpa cumque. - It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters. - Lorem ipsum dolor, sit amet consectetur adipisicing elit. Iure vel officiis ipsum placeat itaque neque dolorem modi perspiciatis dolor distinctio veritatis sapiente, minima corrupti dolores necessitatibus suscipit accusantium dignissimos culpa cumque. - It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters. + {loading ? : error ? {error} : blog && ( + <> + blog hero + +

{blog.title}

+
+

By Jaber Hossain Pranto

+

Published in {blog.category}

+

{blog.createdAt && blog.createdAt.substr(0,10)}

+
+
+ {blog.description} +
+
+ {blog.tags && blog.tags.map((tag, index) => ( + {tag} + ))} +
+
+ + +
+ -
-
- {tags.map((tag, index) => ( - {tag} - ))} -
-
- - -
+ )} +
) diff --git a/client/src/constants/blogConstant.js b/client/src/constants/blogConstant.js index 0cd7695..0215c45 100644 --- a/client/src/constants/blogConstant.js +++ b/client/src/constants/blogConstant.js @@ -2,4 +2,9 @@ export const BLOG_FETCH_REQUEST = "BLOG_FETCH_REQUEST" export const BLOG_FETCH_SUCCESS = "BLOG_FETCH_SUCCESS" export const BLOG_FETCH_FAIL = "BLOG_FETCH_FAIL" +export const BLOG_DETAILS_REQUEST = "BLOG_DETAILS_REQUEST" +export const BLOG_DETAILS_SUCCESS = "BLOG_DETAILS_SUCCESS" +export const BLOG_DETAILS_FAIL = "BLOG_DETAILS_FAIL" + + export const BLOG_CREATE = "BLOG_CREATE" \ No newline at end of file diff --git a/client/src/redux/actions/blogActions.js b/client/src/redux/actions/blogActions.js index f7e7f1f..8ea4dbb 100644 --- a/client/src/redux/actions/blogActions.js +++ b/client/src/redux/actions/blogActions.js @@ -1,5 +1,7 @@ import axios from "axios" -import { BLOG_FETCH_FAIL, BLOG_FETCH_REQUEST, BLOG_FETCH_SUCCESS } from "../../constants/blogConstant" +import { BLOG_DETAILS_REQUEST, BLOG_DETAILS_SUCCESS, BLOG_FETCH_FAIL, BLOG_FETCH_REQUEST, BLOG_FETCH_SUCCESS } from "../../constants/blogConstant" +import { PRODUCT_DETAILS_FAIL } from "../../constants/productConstants" + // @ GET blogs export const fetchBlogs = () => async (dispatch) => { try { @@ -19,6 +21,25 @@ export const fetchBlogs = () => async (dispatch) => { payload: error.response && error.response.data.message ? error.response.data.message : error.message }) } +} + +// Get a blog by id +export const fetchBlogById = (id) => async (dispatch) => { + try { + dispatch({ type: BLOG_DETAILS_REQUEST }) + + const { data } = await axios.get(`/api/blogs/${id}`) + dispatch({ + type: BLOG_DETAILS_SUCCESS, + payload: data + }) + + } catch (error) { + console.log(error); + dispatch({ + type: PRODUCT_DETAILS_FAIL, + payload: error.response && error.response.data.message ? error.response.data.message : error.message + }) + } - } \ No newline at end of file diff --git a/client/src/redux/reducers/blogReducers.js b/client/src/redux/reducers/blogReducers.js index 8fcf108..a7c9be1 100644 --- a/client/src/redux/reducers/blogReducers.js +++ b/client/src/redux/reducers/blogReducers.js @@ -1,4 +1,4 @@ -import { BLOG_FETCH_FAIL, BLOG_FETCH_REQUEST, BLOG_FETCH_SUCCESS } from "../../constants/blogConstant" +import { BLOG_DETAILS_FAIL, BLOG_DETAILS_REQUEST, BLOG_DETAILS_SUCCESS, BLOG_FETCH_FAIL, BLOG_FETCH_REQUEST, BLOG_FETCH_SUCCESS } from "../../constants/blogConstant" export const blogListReducer = ( blogs=[], action) => { switch (action.type) { @@ -14,4 +14,20 @@ export const blogListReducer = ( blogs=[], action) => { default: return blogs } +} + +export const blogDetailsReducer = (state = { blog: {comments:[]} }, action) => { + switch (action.type) { + case BLOG_DETAILS_REQUEST: + return { loading: true, ...state } + + case BLOG_DETAILS_SUCCESS: + return { loading: false, blog: action.payload } + + case BLOG_DETAILS_FAIL: + return { loading: false, error: action.payload } + + default: + return state + } } \ No newline at end of file diff --git a/client/src/store.js b/client/src/store.js index 953de84..00252eb 100644 --- a/client/src/store.js +++ b/client/src/store.js @@ -1,9 +1,7 @@ import { applyMiddleware, combineReducers, createStore } from "redux"; import { composeWithDevTools } from "redux-devtools-extension"; import thunk from "redux-thunk"; -import { - blogListReducer -} from "./redux/reducers/blogReducers"; +import { blogDetailsReducer, blogListReducer } from "./redux/reducers/blogReducers"; import { cartReducer } from "./redux/reducers/cartReducers"; import { orderCreateReducer, orderListReducer @@ -35,7 +33,8 @@ const reducer = combineReducers({ cart: cartReducer, orderCreate: orderCreateReducer, orderList: orderListReducer, - blogList:blogListReducer + blogList: blogListReducer, + blogDetails: blogDetailsReducer }); const cartItemsFromStorage = localStorage.getItem("cartItems") diff --git a/server/controller/blogController.js b/server/controller/blogController.js index 6ab02fc..4e75b5c 100644 --- a/server/controller/blogController.js +++ b/server/controller/blogController.js @@ -25,3 +25,14 @@ export const postBlogs = async (req, res) => { }) } } + +// get a blog by id +export const getBlogById = async (req, res) => { + try { + const blog = await BlogPost.findById(req.params.id) + res.status(200).json(blog) + + } catch (err) { + res.status(404).json({ message: "No blog found" }) + } +} diff --git a/server/routes/blogRoute.js b/server/routes/blogRoute.js index fb2ea67..3c26d24 100644 --- a/server/routes/blogRoute.js +++ b/server/routes/blogRoute.js @@ -1,10 +1,11 @@ import express from 'express' -import { getBlogs, postBlogs } from '../controller/blogController.js' +import { getBlogById, getBlogs, postBlogs } from '../controller/blogController.js' import { isLoggedIn } from '../middlewares/authMiddleware.js' const router = express.Router() router.get("/", getBlogs) -router.post("/",isLoggedIn,postBlogs) +router.post("/", isLoggedIn, postBlogs) +router.get("/:id",getBlogById) export default router \ No newline at end of file