diff --git a/src/ac/index.js b/src/ac/index.js index b1d12b8..3b02572 100644 --- a/src/ac/index.js +++ b/src/ac/index.js @@ -7,6 +7,7 @@ import { LOAD_ALL_ARTICLES, LOAD_ARTICLE, LOAD_ARTICLE_COMMENTS, + LOAD_ALL_COMMENTS, SUCCESS, FAIL, START @@ -87,3 +88,28 @@ export function loadArticleComments(articleId) { callAPI: `/api/comment?article=${articleId}` } } + +export function loadComments({ limit = 5, currentPage = 0 }) { + const offset = currentPage * 5 + return (dispatch) => { + dispatch({ + type: LOAD_ALL_COMMENTS + START + }) + + fetch(`/api/comment?limit=${limit}&offset=${offset}`) + .then((res) => res.json()) + .then(({ total, records }) => + dispatch({ + type: LOAD_ALL_COMMENTS + SUCCESS, + payload: { pagesCount: parseInt(total / limit) }, + response: records + }) + ) + .catch((error) => + dispatch({ + type: LOAD_ALL_COMMENTS + FAIL, + error + }) + ) + } +} diff --git a/src/components/app.js b/src/components/app.js index df3a463..bd78d50 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -4,6 +4,7 @@ import ArticlesPage from './routes/articles-page' import UserForm from './user-form' import Filters from './filters' import Counter from './counter' +import CommentsPage from './routes/comments-page' class App extends Component { render() { @@ -36,6 +37,7 @@ class App extends Component { render={() =>

New Article Page

} /> +

Not Found Page

} /> diff --git a/src/components/comment-list/comments.js b/src/components/comment-list/comments.js new file mode 100644 index 0000000..5eb73b3 --- /dev/null +++ b/src/components/comment-list/comments.js @@ -0,0 +1,74 @@ +import React, { Component, Fragment } from 'react' +import { connect } from 'react-redux' +import { NavLink } from 'react-router-dom' + +import { + commentsListSelector, + commentsLoadingSelector, + commentsPagesCountSelector +} from '../../selectors' + +import { loadComments } from '../../ac' + +class PaginationComments extends Component { + constructor(props) { + super(props) + const { page } = this.props + this.state = { + currentPage: parseInt(page) + } + } + + componentDidMount(oldProps) { + const { loadComments } = this.props + const { currentPage } = this.state + loadComments({ currentPage }) + } + + render() { + const { comments = [], loading, pagesCount } = this.props + const { currentPage } = this.state + + // Эту проверку лучше делать на уровне CommentsPage? + if (currentPage > pagesCount) { + return
{'No comments'}
+ } + + return ( +
+
    + {!loading + ? comments.map((el) => ( +
  • {`${el.id}: ${el.text}`}
  • + )) + : `Loading...`} +
+ 1 ? currentPage - 1 : 1}`} + activeStyle={{ color: 'red' }} + > + Previous + + + Next + +
+ ) + } +} + +export default connect( + (state) => { + return { + comments: commentsListSelector(state), + loading: commentsLoadingSelector(state), + pagesCount: commentsPagesCountSelector(state) + } + }, + { loadComments } +)(PaginationComments) diff --git a/src/components/routes/comments-page.js b/src/components/routes/comments-page.js new file mode 100644 index 0000000..6f2cc44 --- /dev/null +++ b/src/components/routes/comments-page.js @@ -0,0 +1,28 @@ +import React, { Component, Fragment } from 'react' +import { Route } from 'react-router-dom' +import PaginationComments from '../comment-list/comments' + +class CommentsPage extends Component { + static propTypes = {} + + render() { + console.log('---', 'comments-page match: ', this.props.match) + // const title = this.props.match.isExact &&

Select an Article

+ return ( + + + + ) + } + + getComments = ({ match }) => { + console.log('---', 'comments match: ', match) + + if (!match) return

Please Select A Page

+ + const { page } = match.params + return + } +} + +export default CommentsPage diff --git a/src/constants/index.js b/src/constants/index.js index 419b7a9..d7f9169 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -10,6 +10,8 @@ export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE' export const ADD_COMMENT = 'ADD_COMMENT' export const LOAD_ARTICLE_COMMENTS = 'LOAD_ARTICLE_COMMENTS' +export const LOAD_ALL_COMMENTS = 'LOAD_ALL_COMMENTS' + export const START = '_START' export const SUCCESS = '_SUCCESS' export const FAIL = '_FAIL' diff --git a/src/reducer/comments.js b/src/reducer/comments.js index 92f9afd..84d09b9 100644 --- a/src/reducer/comments.js +++ b/src/reducer/comments.js @@ -1,4 +1,10 @@ -import { ADD_COMMENT, LOAD_ARTICLE_COMMENTS, SUCCESS } from '../constants' +import { + ADD_COMMENT, + LOAD_ARTICLE_COMMENTS, + LOAD_ALL_COMMENTS, + START, + SUCCESS +} from '../constants' import { Record, OrderedMap } from 'immutable' import { arrToMap } from './utils' @@ -8,8 +14,13 @@ const CommentRecord = Record({ user: null }) +// Реализованная пагинация ломает работу комментариев в связке со статьей const ReducerRecord = Record({ - entities: new OrderedMap({}) + entities: new OrderedMap({}), + pagesCount: null, + loading: false, + loaded: false, + error: null }) export default (state = new ReducerRecord(), action) => { @@ -28,6 +39,19 @@ export default (state = new ReducerRecord(), action) => { case LOAD_ARTICLE_COMMENTS + SUCCESS: return state.mergeIn(['entities'], arrToMap(response, CommentRecord)) + case LOAD_ALL_COMMENTS + START: + return state.set('loading', true).set('loaded', false) + + case LOAD_ALL_COMMENTS + SUCCESS: + return ( + state + // Не сохраняем в store предыдущий набор статей + .set(['entities'], arrToMap(response, CommentRecord)) + .set('pagesCount', payload.pagesCount) + .set('loading', false) + .set('loaded', true) + ) + default: return state } diff --git a/src/selectors/index.js b/src/selectors/index.js index 10ae8e3..3c08fd5 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -9,9 +9,19 @@ export const articleListSelector = createSelector( articlesMapSelector, (articlesMap) => articlesMap.valueSeq().toArray() ) -export const commentsSelector = (state) => state.comments + +export const commentsMapSelector = (state) => state.comments.entities export const idSelector = (_, props) => props.id +export const commentsListSelector = createSelector( + commentsMapSelector, + (commentsMap) => commentsMap.valueSeq().toArray() +) + +export const commentsPagesCountSelector = (state) => state.comments.pagesCount + +export const commentsLoadingSelector = (state) => state.comments.loading + export const filtratedArticlesSelector = createSelector( selectionSelector, dateRangeSelector, @@ -32,7 +42,7 @@ export const filtratedArticlesSelector = createSelector( ) export const createCommentSelector = () => - createSelector(commentsSelector, idSelector, (comments, id) => { + createSelector(commentsListSelector, idSelector, (comments, id) => { return comments.getIn(['entities', id]) })