Skip to content

Commit

Permalink
feat: create comments in different post
Browse files Browse the repository at this point in the history
- Add CommentForm
- Create new action and reducer to handle adding new comment
- Add `RESET_COMMENT_AFTER_CHANGE_PATH` to reinitialize comments list when switch to different post
  • Loading branch information
iamthuypham committed Nov 23, 2017
1 parent c7b4c42 commit 0ef028c
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 19 deletions.
2 changes: 1 addition & 1 deletion frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class App extends Component {
<main>
<Route exact path='/' render={(props)=><AllPosts routing={props}/>}/>
<Route exact path='/:category' render={(props)=><PostsByCategory routing={props}/>}/>
<Route exact path='/:category/:post_id' component={PostWithComments}/>
<Route exact path='/:category/:post_id' render={(props)=><PostWithComments routing={props}/>}/>
</main>
</div>
)
Expand Down
65 changes: 65 additions & 0 deletions frontend/src/comment/CommentForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';

const uuidv4 = require('uuid/v4');

class CommentForm extends Component {
constructor(props) {
super(props);
this.state = ({
author:'',
body:'',
deleted:false,
parentDeleted:false,
voteScore:0
})
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSubmit(e) {
e.preventDefault();
const newComment = {
id: uuidv4(),
author:this.state.author,
body:this.state.body,
deleted:this.state.deleted,
parentId: this.props.post.id,
parentDeleted:this.state.deleted,
voteScore:this.state.voteScore,
timestamp: Date.now(),
}
this.props.onSubmitRequest(newComment)
}

handleChange(e){
const { name, value } = e.target;
this.setState({
[name]: value,
});
}

componentWillReceiveProps(nextProps) {
if (this.props.comments != nextProps.comments){
this.setState({
author:'',
body:''
})
}
}
componentDidMount() {
}
render() {
const { author, body } = this.state
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type="text" name="body" placeholder="New Comment" value={body} onChange={this.handleChange} required/>
<input type="text" name="author" placeholder="Your Name" value={author} onChange={this.handleChange} required/>
<input type='submit' value='Submit'/>
</form>
</div>
)
}
}

export default CommentForm;
34 changes: 34 additions & 0 deletions frontend/src/comment/action.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
export const GET_THIS_POST_COMMENTS = 'GET_THIS_POST_COMMENTS'
export const ADD_COMMENT = 'ADD_COMMENT'
export const RESET_CURRENT_COMMENT_AFTER_CHANGE_PATH = 'RESET_CURRENT_COMMENT_AFTER_CHANGE_PATH'

const reset = () => ({
type: RESET_CURRENT_COMMENT_AFTER_CHANGE_PATH
}
)

const getThisPostComments = comments => ({
type: GET_THIS_POST_COMMENTS,
comments
}
)

const addComment = (comment, comments) => ({
type: ADD_COMMENT,
comment,
comments
}
)
export function resetComments() {
return function (dispatch) {
dispatch(reset())
}
}

export function fetchThisPostComments(postId) {
return function (dispatch) {
const url = `${process.env.REACT_APP_BACKEND}/posts/${postId}/comments`
Expand All @@ -14,4 +33,19 @@ export function fetchThisPostComments(postId) {
.then(data => dispatch(getThisPostComments(data))
);
};
}

export function fetchAddComment(comment, comments) {
return function (dispatch) {
const url = `${process.env.REACT_APP_BACKEND}/comments`

const request = new Request(url, {
method: 'post',
body: JSON.stringify(comment),
headers: { 'Authorization': 'whatever-you-want', "Content-Type": "application/json",
credentials: 'include'},
});

return fetch(request).then(res => res.json()).then(data => dispatch(addComment(data, comments)))
}
}
31 changes: 27 additions & 4 deletions frontend/src/comment/reducer.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
import { combineReducers } from 'redux'

import {
GET_THIS_POST_COMMENTS
GET_THIS_POST_COMMENTS,
ADD_COMMENT,
RESET_CURRENT_COMMENT_AFTER_CHANGE_PATH
} from './action'

function getThisPostComments (state={
isFetching: true,
comments: []
}, action) {
const { comments } = action
switch (action.type) {
case GET_THIS_POST_COMMENTS:
return Object.assign({}, state, {
isFetching: false,
comments
})
default:
return state
}
}

function CurrentCommentsReducer (state={
comments: []
}, action) {
const { comment, comments } = action
switch (action.type) {
case ADD_COMMENT:
return Object.assign({}, state, {
comments:[
...comments,
comment
]
})
case RESET_CURRENT_COMMENT_AFTER_CHANGE_PATH:
return Object.assign({}, state, {
comments:[
]
})
default:
return state
}
}

export default combineReducers({
getThisPostComments
getThisPostComments,
CurrentCommentsReducer
})
43 changes: 32 additions & 11 deletions frontend/src/post/PostWithComments.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,62 @@ import { connect } from 'react-redux';
import { Route, Link } from 'react-router-dom';

import { fetchOnePost } from './action';
import { fetchThisPostComments } from '../comment/action';
import { fetchThisPostComments, fetchAddComment, resetComments } from '../comment/action';
import Comment from '../comment/Comment';
import CommentForm from '../comment/CommentForm';

class PostWithComments extends Component {
constructor(props) {
super(props);
this.handleSubmitRequest = this.handleSubmitRequest.bind(this)
}
componentDidMount() {
const postIdParam = this.props.match.params.post_id
console.log(this.props)
const postIdParam = this.props.routing.match.params.post_id
this.props.dispatchFetchOnePost(postIdParam)
//this.props.dispatchFetchThisPostComments(postIdParam)
this.props.dispatchResetComments()
this.props.dispatchFetchThisPostComments(postIdParam)
}
handleSubmitRequest(comment) {
this.props.dispatchFetchAddComment(comment,this.props.commentsByPost)
}

render() {
const { isFetching, post, comments } = this.props
const { post, commentsByPost } = this.props
console.log(this.props)
return (
<div>
<div>{post.author} - {post.title} - {post.body} - {post.voteScore}</div>

<div>Comments</div>
{commentsByPost && commentsByPost.map((comment) =>
comment.id && <Comment key={comment.id} comment={comment}/>
)}
<div>Add a comment</div>
<CommentForm post={post} comments={commentsByPost} onSubmitRequest={this.handleSubmitRequest}/>
</div>
)
}
}

function mapStateToProps (state) {
console.log(state)
const { post, isFetching } = state.PostReducer.getOnePostReducer
return {post, isFetching}
function mapStateToProps (state, ownProps) {
const currentPostId = ownProps.routing.match.params.post_id
let commentsByPost
const { post } = state.PostReducer.getOnePostReducer
const { comments } = state.CommentReducer.getThisPostComments
const currentComments = state.CommentReducer.CurrentCommentsReducer.comments

if (currentComments.length) {
commentsByPost = currentComments.filter((comment) => comment.parentId === currentPostId)
} else {
commentsByPost = comments.filter((comment) => comment.parentId === currentPostId)
}
return {post, commentsByPost}
}

const mapDispatchToProps = (dispatch) => ({
dispatchFetchOnePost: (postId) => dispatch(fetchOnePost(postId)),

dispatchResetComments: () => dispatch(resetComments()),
dispatchFetchThisPostComments: (postId) => dispatch(fetchThisPostComments(postId)),
dispatchFetchAddComment: (comment, comments) => dispatch(fetchAddComment(comment, comments)),
})

export default connect(
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/post/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export function fetchAddPost(post, posts) {
const request = new Request(url, {
method: 'post',
body: JSON.stringify(post),
headers: { 'Authorization': 'whatever-you-want', "Content-Type": "application/json", },
credentials: 'include'
headers: { 'Authorization': 'whatever-you-want', "Content-Type": "application/json",
credentials: 'include'}
});

return fetch(request).then(res => res.json()).then(data => dispatch(addPost(data, posts)))
Expand Down
1 change: 0 additions & 1 deletion frontend/src/post/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function getOnePostReducer (state={
post: []
}, action) {
const { post } = action
console.log(post)
switch (action.type) {
case GET_ONE_POST:
return Object.assign({}, state, {
Expand Down

0 comments on commit 0ef028c

Please sign in to comment.