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 (
-
- 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](https://images.unsplash.com/photo-1441974231531-c6227db76b6e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80)
+
+
{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}
+ ))}
+
+
+ 5
+ 4
+
+ >
-
-
- {tags.map((tag, index) => (
- {tag}
- ))}
-
-
- 5
- 4
-
+ )}
+
)
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