Skip to content

Commit

Permalink
feat: create blog page and display blog posts
Browse files Browse the repository at this point in the history
  • Loading branch information
wu-ciesielska committed Nov 27, 2023
1 parent 4fcda56 commit 4a858be
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/app/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Home,
PlayWithModel,
Prediction,
Blog,
} from '../screens';

import {
Expand Down Expand Up @@ -120,6 +121,7 @@ const App = (props) => {
<Route exact path={ROUTES.HOME} component={Home} />
<Route path={ROUTES.ABOUT} component={About} />
<Route path={ROUTES.ADMIN} component={Admin} />
<Route path={ROUTES.BLOG} component={Blog} />
<Route path={ROUTES.RESOURCES} component={Resources} />
<Route path={ROUTES.TRAPPING_DATA} component={TrappingData} />
<Route path={ROUTES.PLAY_WITH_MODEL} component={PlayWithModel} />
Expand Down
1 change: 1 addition & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const CHART_MODES = {
const ROUTES = {
ABOUT: '/about',
ADMIN: '/admin',
BLOG: '/blog',
HOME: '/',
RESOURCES: '/resources',
PLAY_WITH_MODEL: '/play-with-model',
Expand Down
2 changes: 1 addition & 1 deletion src/screens/admin/components/blog-post-form/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
transform: translate(-50%, -50%);
min-width: 100%;
min-height: 100%;
width: auto;
width: inherit;
height: auto;
}
}
14 changes: 4 additions & 10 deletions src/screens/admin/components/blog-posts/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import React, { useEffect, useState } from 'react';
import Modal from 'react-modal';

import EditBlogPost from '../edit-blog-post';
import { getDateToDisplay, sortBlogPosts } from '../../../../utils';

import './style.scss';

const BlogPost = ({ post, onClickEdit, onDelete }) => {
const date = new Date(post.date_created);
const dateToDisplay = `${date.getMonth()}/${date.getDate()}/${date.getFullYear()}`;

const onClickDelete = () => {
onDelete(post.id);
};
Expand All @@ -19,7 +18,7 @@ const BlogPost = ({ post, onClickEdit, onDelete }) => {
{post.title}
</div>
<div className="blog-post-date">
{dateToDisplay}
{getDateToDisplay(post.date_created)}
</div>
</div>
<div className="blog-post-action-buttons">
Expand Down Expand Up @@ -80,12 +79,7 @@ const BlogPosts = (props) => {
}, [getAllBlogPostsByAuthor]);

// Sort posts from the newest to the oldest
const sortedBlogPosts = blogPosts.sort((a, b) => {
const dateA = new Date(a.date_created);
const dateB = new Date(b.date_created);

return dateB - dateA;
});
const sortedBlogPosts = sortBlogPosts(blogPosts);

const handleFormSubmit = async (formData) => {
const closeModal = () => { setShowEditForm(false); };
Expand Down
32 changes: 32 additions & 0 deletions src/screens/blog/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { useEffect } from 'react';

import BlogPost from './components';
import { sortBlogPosts } from '../../utils';

import './style.scss';

const Blog = (props) => {
const {
blogPosts,
getAllBlogPosts,
} = props;

useEffect(() => {
getAllBlogPosts();
}, [getAllBlogPosts]);

const sortedBlogPosts = sortBlogPosts(blogPosts);

return (
<div className="blog-page-container">
<div id="overview-text">
<h1 id="title">Blog</h1>
</div>
{sortedBlogPosts.length > 0
? sortedBlogPosts.map((post) => <BlogPost post={post} />)
: <div className="blog-page-no-posts">There are no blog posts yet</div>}
</div>
);
};

export default Blog;
28 changes: 28 additions & 0 deletions src/screens/blog/components/blog-post/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import { formatPostDates } from '../../../../utils';

import './style.scss';

const BlogPost = ({ post }) => {
const {
title,
body,
date_created: createdAt,
date_edited: editedAt,
image,
author,
} = post;

return (
<div className="blog-page-blog-post-container page-container">
<div className="blog-page-blog-post-title">{title}</div>
<div className="blog-page-blog-post-author">{`by ${author}`}</div>
{image && <img className="blog-page-blog-post-picture" src={`${global.API_URL}${image}`} alt="whatever" />}
<div className="blog-page-blog-post-body">{body}</div>
<div className="blog-page-blog-post-date">{formatPostDates(createdAt, editedAt)}</div>
</div>
);
};

export default BlogPost;
3 changes: 3 additions & 0 deletions src/screens/blog/components/blog-post/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import BlogPost from './component';

export default BlogPost;
44 changes: 44 additions & 0 deletions src/screens/blog/components/blog-post/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.blog-page {
&-blog-post {
&-container {
margin: 30px auto;
width: 100%;
box-sizing: border-box;
}

&-title {
font-size: 24px;
font-weight: 600;
}

&-author {
margin-bottom: 20px;
margin-top: 6px;
}

&-picture {
max-width: 100%;
height: auto;
max-height: 500px;
margin: 30px auto 50px;
}

&-date {
font-style: italic;
font-size: 14px;
margin-top: 30px;
width: 100%;
text-align: right;
}

&-date,
&-author {
font-style: italic;
color: #73767e;
}

&-body {
white-space: pre-line;
}
}
}
3 changes: 3 additions & 0 deletions src/screens/blog/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import BlogPost from './blog-post';

export default BlogPost;
21 changes: 21 additions & 0 deletions src/screens/blog/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { getAllBlogPosts } from '../../state/actions/blog';
import Blog from './component';

const mapStateToProps = (state) => {
const {
blog: {
blogPosts,
},
} = state;

return { blogPosts };
};

const mapDispatchToProps = (dispatch) => {
return {
getAllBlogPosts: () => dispatch(getAllBlogPosts()),
};
};

export default connect(mapStateToProps, mapDispatchToProps)(Blog);
14 changes: 14 additions & 0 deletions src/screens/blog/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.blog-page-container {
max-width: 1000px;
margin: auto;
display: flex;
flex-direction: column;
align-items: center;
}

.blog-page-no-posts {
font-size: 26px;
width: 100%;
text-align: center;
color: #73767e;
}
2 changes: 2 additions & 0 deletions src/screens/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import About from './about';
import Admin from './admin';
import Blog from './blog';
import Resources from './resources';
import TrappingData from './trapping-data';
import Home from './home';
Expand All @@ -9,6 +10,7 @@ import Prediction from './prediction';
export {
About,
Admin,
Blog,
Resources,
TrappingData,
Home,
Expand Down
18 changes: 17 additions & 1 deletion src/state/actions/blog.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const ActionTypes = {
API_ERROR: 'API_ERROR',
CLEAR_API_ERROR: 'CLEAR_API_ERROR',
SET_BLOG_POSTS_BY_USER_DATA: 'SET_BLOG_POSTS_BY_USER_DATA',
GET_ALL_BLOG_POSTS: 'GET_ALL_BLOG_POSTS',
EDIT_BLOG_POST: 'EDIT_BLOG_POST',
DELETE_BLOG_POST: 'DELETE_BLOG_POST',
CREATE_BLOG_POST: 'CREATE_BLOG_POST',
Expand All @@ -28,6 +29,21 @@ export const createBlogPost = (fields, onSuccess = () => {}) => {
};
};

export const getAllBlogPosts = () => {
return async (dispatch) => {
try {
const blogPosts = await BlogService.getAllBlogPosts();
dispatch({ type: ActionTypes.GET_ALL_BLOG_POSTS, payload: blogPosts });
} catch (error) {
dispatch({
type: ActionTypes.API_ERROR,
payload: 'GET ALL BLOG POSTS',
error,
});
}
};
};

export const getAllBlogPostsByAuthor = (onSuccess = () => {}, onError = () => {}) => {
return async (dispatch) => {
try {
Expand All @@ -38,7 +54,7 @@ export const getAllBlogPostsByAuthor = (onSuccess = () => {}, onError = () => {}
dispatch({
type: ActionTypes.API_ERROR,
payload: {
action: 'GET ALL BLOG POSTS',
action: 'GET ALL BLOG POSTS BY USER',
error,
},
});
Expand Down
4 changes: 4 additions & 0 deletions src/state/reducers/blog.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ActionTypes } from '../actions';

const initialState = {
blogPosts: [],
blogPostsByUser: [],
error: null,
};
Expand All @@ -15,6 +16,9 @@ const BlogReducer = (state = initialState, action) => {
case ActionTypes.SET_BLOG_POSTS_BY_USER_DATA:
return { ...state, blogPostsByUser: action.payload };

case ActionTypes.GET_ALL_BLOG_POSTS:
return { ...state, blogPosts: action.payload };

case ActionTypes.EDIT_BLOG_POST: {
const updatedBlogPosts = state.blogPostsByUser.map(
(post) => (post._id === action.payload._id
Expand Down
33 changes: 33 additions & 0 deletions src/utils/blog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Sort posts from the newest to the oldest
const sortBlogPosts = (blogPosts) => blogPosts.sort((a, b) => {
const dateA = new Date(a.date_created);
const dateB = new Date(b.date_created);

return dateB - dateA;
});

// Return string with US date format
const getDateToDisplay = (dateToParse) => {
const date = new Date(dateToParse);
return `${date.getMonth()}/${date.getDate()}/${date.getFullYear()}`;
};

// Return string with blog post creation and editing dates
const formatPostDates = (created, updated) => {
const options = {
year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit',
};
const createdDate = new Date(created).toLocaleString('en-US', options);
const updatedDate = new Date(updated).toLocaleString('en-US', options);

let dateString = `Posted on ${createdDate}`;
if (updated && created !== updated) {
dateString += `, Last updated on ${updatedDate}`;
}

return dateString;
};

export {
sortBlogPosts, getDateToDisplay, formatPostDates,
};
9 changes: 9 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,29 @@ import {
toQueryParams,
} from './network';

import {
sortBlogPosts,
getDateToDisplay,
formatPostDates,
} from './blog';

export {
downloadCsv,
getAuthTokenFromStorage,
getChartModeFromStorage,
getDataModeFromStorage,
getDateToDisplay,
getMapboxRDNameFormat,
getStateAbbreviationFromStateName,
getStateNameFromAbbreviation,
getUserIdFromStorage,
formatPostDates,
removeAuthTokenFromStorage,
removeUserIdFromStorage,
setAuthTokenInStorage,
setChartModeInStorage,
setDataModeInStorage,
setUserIdInStorage,
sortBlogPosts,
toQueryParams,
};

0 comments on commit 4a858be

Please sign in to comment.