diff --git a/src/AC/index.js b/src/AC/index.js index 27d70d1..7b7c280 100644 --- a/src/AC/index.js +++ b/src/AC/index.js @@ -1,5 +1,5 @@ import {DELETE_ARTICLE, INCREMENT, CHANGE_DATE_RANGE, CHANGE_SELECTION, ADD_COMMENT, - LOAD_ALL_ARTICLES, LOAD_ARTICLE, START, SUCCESS, FAIL + LOAD_ALL_ARTICLES, LOAD_ALL_COMMENTS, LOAD_ARTICLE, START, SUCCESS, FAIL } from '../constants' export function increment() { @@ -44,6 +44,13 @@ export function loadAllArticles() { } } +export function loadAllComments() { + return { + type: LOAD_ALL_COMMENTS, + callAPI: '/api/comment' + } +} + export function loadArticle(id) { return (dispatch) => { dispatch({ @@ -51,18 +58,16 @@ export function loadArticle(id) { payload: { id } }) - setTimeout(() => { - fetch(`/api/article/${id}`) - .then(res => res.json()) - .then(response => dispatch({ - type: LOAD_ARTICLE + SUCCESS, - payload: { id, response } - })) - .catch(error => dispatch({ - type: LOAD_ARTICLE + FAIL, - payload: { id, error } - })) - }, 1000) + fetch(`/api/article/${id}`) + .then(res => res.json()) + .then(response => dispatch({ + type: LOAD_ARTICLE + SUCCESS, + payload: { id, response } + })) + .catch(error => dispatch({ + type: LOAD_ARTICLE + FAIL, + payload: { id, error } + })) } } diff --git a/src/components/Comment.js b/src/components/Comment.js index 75f1085..8f08e65 100644 --- a/src/components/Comment.js +++ b/src/components/Comment.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import {connect} from 'react-redux' import {commentSelectorFactory} from '../selectors' -function Comment({comment}) { +function Comment({comment = {}}) { return (

{comment.text} by {comment.user}

@@ -20,14 +20,14 @@ Comment.propTypes = { }).isRequired } -const mapStateToProps = () => { - const commentSelector = commentSelectorFactory() +// const mapStateToProps = () => { +// const commentSelector = commentSelectorFactory() - return (state, ownProps) => { - return { - comment: commentSelector(state, ownProps) - } - } -} +// return (state, ownProps) => { +// return { +// comment: commentSelector(state, ownProps) +// } +// } +// } -export default connect(mapStateToProps)(Comment) \ No newline at end of file +export default Comment diff --git a/src/components/CommentList.js b/src/components/CommentList.js index e35ff75..fb6360a 100644 --- a/src/components/CommentList.js +++ b/src/components/CommentList.js @@ -3,15 +3,22 @@ import PropTypes from 'prop-types' import Comment from './Comment' import CommentForm from './CommentForm' import toggleOpen from '../decorators/toggleOpen' +import {connect} from 'react-redux' +import {loadAllComments} from '../AC' +import Loader from './Loader' -function CommentList({article, isOpen, toggleOpen}) { - const text = isOpen ? 'hide comments' : 'show comments' - return ( -
- - {getBody({article, isOpen})} -
- ) +class CommentList extends Component { + render() { + let { article, isOpen, toggleOpen, loadAllComments, loaded, loading, comments } = this.props + + const text = isOpen ? 'hide comments' : 'show comments' + return ( +
+ + {isOpen && } +
+ ) + } } CommentList.propTypes = { @@ -21,23 +28,43 @@ CommentList.propTypes = { toggleOpen: PropTypes.func } -function getBody({article: {comments = [], id}, isOpen}) { - if (!isOpen) return null - if (!comments.length) return ( -
-

No comments yet

- -
- ) - - return ( -
- - -
- ) +class Comments extends Component { + componentDidMount() { + const {loaded, loading, loadAllComments} = this.props + if (!loaded || !loading) loadAllComments() + } + + render() { + let {article: {comments = [], id}, loading, commentsState} = this.props + + if (loading) return + + if (!comments.length) return ( +
+

No comments yet

+ +
+ ) + + return ( +
+
    + {comments.map(id => +
  • + +
  • + )} +
+ +
+ ) + } } -export default toggleOpen(CommentList) \ No newline at end of file +export default toggleOpen(connect((state) => { + return { + comments: state.comments.comments, + loading: state.comments.loading, + loaded: state.comments.loaded + } +}, {loadAllComments})(CommentList)) diff --git a/src/constants.js b/src/constants.js index 267c907..dbd58e1 100644 --- a/src/constants.js +++ b/src/constants.js @@ -11,4 +11,6 @@ export const ADD_COMMENT = 'ADD_COMMENT' export const START = '_START' export const SUCCESS = '_SUCCESS' -export const FAIL = '_FAIL' \ No newline at end of file +export const FAIL = '_FAIL' + +export const LOAD_ALL_COMMENTS = 'LOAD_ALL_COMMENTS' diff --git a/src/helpers.js b/src/helpers.js index 9a0477f..c2bf9cc 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -8,4 +8,4 @@ export function arrToMap(arr, DataRecord = Map) { export function mapToArr(obj) { return obj.valueSeq().toArray() -} \ No newline at end of file +} diff --git a/src/middlewares/api.js b/src/middlewares/api.js index 2ccf7ed..14e8855 100644 --- a/src/middlewares/api.js +++ b/src/middlewares/api.js @@ -4,15 +4,10 @@ export default store => next => action => { const {callAPI, type, ...rest} = action if (!callAPI) return next(action) - next({ - ...rest, type: type + START - }) + next({ ...rest, type: type + START }) - setTimeout(() => { - fetch(callAPI) - .then(res => res.json()) - .then(response => next({...rest, type: type + SUCCESS, response})) - .catch(error => next({...rest, type: type + FAIL, error})) - }, 1000) - -} \ No newline at end of file + fetch(callAPI) + .then(res => res.json()) + .then(response => next({ ...rest, type: type + SUCCESS, response })) + .catch(error => next({ ...rest, type: type + FAIL, error })) +} diff --git a/src/reducer/articles.js b/src/reducer/articles.js index 8700ced..ad1bed1 100644 --- a/src/reducer/articles.js +++ b/src/reducer/articles.js @@ -49,4 +49,4 @@ export default (articleState = defaultState, action) => { } return articleState -} \ No newline at end of file +} diff --git a/src/reducer/comments.js b/src/reducer/comments.js index bc6a5d5..d9a7b4e 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,16 +1,41 @@ import {normalizedComments as defaulComments} from '../fixtures' -import {ADD_COMMENT} from '../constants' +import {ADD_COMMENT, LOAD_ALL_COMMENTS, START, SUCCESS} from '../constants' import {arrToMap} from '../helpers' +import {OrderedMap, Record} from 'immutable' -const commentsMap = arrToMap(defaulComments) +const CommentRecord = Record({ + id: null, + user: '', + text: '' +}) -export default (commentsState = commentsMap, action) => { - const {type, payload, randomId} = action +const ReducerState = Record({ + comments: new OrderedMap({}), + loading: false, + loaded: false +}) + +const defaultState = new ReducerState() + +export default (commentsState = defaultState, action) => { + const {type, payload, randomId, response} = action switch (type) { case ADD_COMMENT: - return {...commentsState, [randomId]: payload.comment} + return commentsState.updateIn([randomId]: payload.comment) + + case LOAD_ALL_COMMENTS + START: + return commentsState.set('loading', true) + + case LOAD_ALL_COMMENTS + SUCCESS:{ + let comments = arrToMap(Array.prototype.slice.call(response.records), CommentRecord) + + return commentsState + .set('comments', comments) + .set('loading', false) + .set('loaded', true) + } } return commentsState -} \ No newline at end of file +}