diff --git a/src/ac/index.js b/src/ac/index.js
index 6acd6da..462aa20 100644
--- a/src/ac/index.js
+++ b/src/ac/index.js
@@ -2,7 +2,8 @@ import {
INCREMENT,
DELETE_ARTICLE,
CHANGE_DATE_RANGE,
- CHANGE_SELECTION
+ CHANGE_SELECTION,
+ ADD_COMMENT
} from '../constants'
export function increment() {
@@ -31,3 +32,10 @@ export function changeSelection(selected) {
payload: { selected }
}
}
+
+export function addComment(payload) {
+ return {
+ type: ADD_COMMENT,
+ payload: payload
+ }
+}
diff --git a/src/components/article-list.js b/src/components/article-list.js
index 9650e42..2068197 100644
--- a/src/components/article-list.js
+++ b/src/components/article-list.js
@@ -7,7 +7,7 @@ import { filtratedArticlesSelector } from '../selectors'
export class ArticleList extends Component {
static propTypes = {
- articles: PropTypes.array.isRequired,
+ articles: PropTypes.object.isRequired,
fetchData: PropTypes.func,
//from accordion decorator
@@ -22,11 +22,11 @@ export class ArticleList extends Component {
get items() {
const { articles, openItemId, toggleOpenItem } = this.props
- return articles.map((article) => (
-
+ return Object.keys(articles).map((id) => (
+
diff --git a/src/components/article/index.js b/src/components/article/index.js
index 41fb2d5..becb29e 100644
--- a/src/components/article/index.js
+++ b/src/components/article/index.js
@@ -63,7 +63,7 @@ class Article extends PureComponent {
return (
)
}
diff --git a/src/components/comment-list/index.js b/src/components/comment-list/index.js
index 7412972..221fbae 100644
--- a/src/components/comment-list/index.js
+++ b/src/components/comment-list/index.js
@@ -1,8 +1,11 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
import CSSTransition from 'react-addons-css-transition-group'
import Comment from '../comment'
+import PublishForm from '../publish-form'
import toggleOpen from '../../decorators/toggleOpen'
+import { addComment } from '../../ac'
import './style.css'
class CommentList extends Component {
@@ -49,6 +52,7 @@ class CommentList extends Component {
) : (
No comments yet
)}
+
)
}
@@ -64,6 +68,14 @@ class CommentList extends Component {
)
}
+
+ submitComment(data) {
+ const { articleId, addComment } = this.props
+ addComment({ ...data, articleId })
+ }
}
-export default toggleOpen(CommentList)
+export default connect(
+ null,
+ { addComment }
+)(toggleOpen(CommentList))
diff --git a/src/components/filters/select.js b/src/components/filters/select.js
index a56ed53..ff1b984 100644
--- a/src/components/filters/select.js
+++ b/src/components/filters/select.js
@@ -6,7 +6,7 @@ import { changeSelection } from '../../ac'
class SelectFilter extends Component {
static propTypes = {
- articles: PropTypes.array.isRequired
+ articles: PropTypes.object.isRequired
}
handleChange = (selected) => {
@@ -14,9 +14,10 @@ class SelectFilter extends Component {
}
get options() {
- return this.props.articles.map((article) => ({
- label: article.title,
- value: article.id
+ const { articles } = this.props
+ return Object.keys(articles).map((id) => ({
+ label: articles[id].title,
+ value: id
}))
}
diff --git a/src/components/publish-form.js b/src/components/publish-form.js
new file mode 100644
index 0000000..d50d567
--- /dev/null
+++ b/src/components/publish-form.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+class PublishForm extends Component {
+ static propTypes = {
+ handler: PropTypes.func.isRequired
+ }
+
+ state = {
+ text: '',
+ user: ''
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ )
+ }
+
+ handleInputChange(e) {
+ const val = e.target.value
+ const prop = e.target.name
+ this.setState({ [prop]: val })
+ }
+
+ handlePublishClick() {
+ const { handler } = this.props
+
+ handler({ ...this.state })
+ }
+}
+
+export default PublishForm
diff --git a/src/constants/index.js b/src/constants/index.js
index e1fd7eb..4f21432 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -4,3 +4,5 @@ export const DELETE_ARTICLE = 'DELETE_ARTICLE'
export const CHANGE_SELECTION = 'CHANGE_SELECTION'
export const CHANGE_DATE_RANGE = 'CHANGE_DATE_RANGE'
+
+export const ADD_COMMENT = 'ADD_COMMENT'
diff --git a/src/middlewares/id-generator.js b/src/middlewares/id-generator.js
new file mode 100644
index 0000000..e0ae3a2
--- /dev/null
+++ b/src/middlewares/id-generator.js
@@ -0,0 +1,9 @@
+import crypto from 'crypto'
+import { ADD_COMMENT } from '../constants'
+
+export default (store) => (next) => (action) => {
+ if (action.type === ADD_COMMENT) {
+ action.payload.id = crypto.randomBytes(16).toString('hex')
+ }
+ next(action)
+}
diff --git a/src/middlewares/index.js b/src/middlewares/index.js
new file mode 100644
index 0000000..d8cd25c
--- /dev/null
+++ b/src/middlewares/index.js
@@ -0,0 +1,4 @@
+import logger from './logger'
+import idGenerator from './id-generator'
+
+export default [logger, idGenerator]
diff --git a/src/reducer/articles.js b/src/reducer/articles.js
index 8a41996..ee83565 100644
--- a/src/reducer/articles.js
+++ b/src/reducer/articles.js
@@ -1,5 +1,13 @@
-import { normalizedArticles as defaultArticles } from '../fixtures'
-import { DELETE_ARTICLE } from '../constants'
+import { normalizedArticles } from '../fixtures'
+import { DELETE_ARTICLE, ADD_COMMENT } from '../constants'
+
+const defaultArticles = normalizedArticles.reduce(
+ (acc, article) => ({
+ ...acc,
+ [article.id]: article
+ }),
+ {}
+)
export default (articlesState = defaultArticles, action) => {
const { type, payload } = action
@@ -8,6 +16,16 @@ export default (articlesState = defaultArticles, action) => {
case DELETE_ARTICLE:
return articlesState.filter((article) => article.id !== payload.id)
+ case ADD_COMMENT:
+ const comments = articlesState[payload.articleId].comments || []
+ return {
+ ...articlesState,
+ [payload.articleId]: {
+ ...articlesState[payload.articleId],
+ comments: [].concat(payload.id, comments)
+ }
+ }
+
default:
return articlesState
}
diff --git a/src/reducer/comments.js b/src/reducer/comments.js
index 1cb52e1..e800f99 100644
--- a/src/reducer/comments.js
+++ b/src/reducer/comments.js
@@ -1,4 +1,4 @@
-import {} from '../constants'
+import { ADD_COMMENT } from '../constants'
import { normalizedComments } from '../fixtures'
const defaultComments = normalizedComments.reduce(
@@ -10,9 +10,19 @@ const defaultComments = normalizedComments.reduce(
)
export default (state = defaultComments, action) => {
- const { type } = action
+ const { type, payload } = action
switch (type) {
+ case ADD_COMMENT:
+ return {
+ ...state,
+ [payload.id]: {
+ id: payload.id,
+ user: payload.user,
+ text: payload.text
+ }
+ }
+
default:
return state
}
diff --git a/src/selectors/index.js b/src/selectors/index.js
index b4a2b29..39fce19 100644
--- a/src/selectors/index.js
+++ b/src/selectors/index.js
@@ -13,15 +13,20 @@ export const filtratedArticlesSelector = createSelector(
(selected, dateRange, articles) => {
console.log('---', 'article list selector')
const { from, to } = dateRange
+ const ids = selected.length
+ ? selected.map((item) => item.value)
+ : Object.keys(articles)
- return articles.filter((article) => {
+ return ids.reduce((acc, id) => {
+ const article = articles[id]
const published = Date.parse(article.date)
- return (
- (!selected.length ||
- selected.find((selected) => selected.value === article.id)) &&
- (!from || !to || (published > from && published < to))
- )
- })
+ return !from || !to || (published > from && published < to)
+ ? {
+ ...acc,
+ [id]: article
+ }
+ : { ...acc }
+ }, {})
}
)
diff --git a/src/store/index.js b/src/store/index.js
index 847f3d6..78883ee 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,8 +1,8 @@
import { createStore, applyMiddleware } from 'redux'
import reducer from '../reducer'
-import logger from '../middlewares/logger'
+import middlewares from '../middlewares'
-const enhancer = applyMiddleware(logger)
+const enhancer = applyMiddleware(...middlewares)
const store = createStore(reducer, enhancer)