-
Notifications
You must be signed in to change notification settings - Fork 1
solution #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
solution #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,85 +1,144 @@ | ||||||
| import React from 'react'; | ||||||
| import React, { Component } from 'react'; | ||||||
| import { TodoList } from './components/TodoList/TodoList'; | ||||||
| import NewTodo from './components/NewTodo/NewTodo'; | ||||||
| import { TodosFilter } from './components/TodosFilter/TodosFilter'; | ||||||
|
|
||||||
| function App() { | ||||||
| return ( | ||||||
| <section className="todoapp"> | ||||||
| <header className="header"> | ||||||
| <h1>todos</h1> | ||||||
| class App extends Component { | ||||||
| state = { | ||||||
| todos: [], | ||||||
| showParam: 'all', | ||||||
| }; | ||||||
|
|
||||||
| <input | ||||||
| className="new-todo" | ||||||
| placeholder="What needs to be done?" | ||||||
| /> | ||||||
| </header> | ||||||
| addTodo = (todo) => { | ||||||
| this.setState(prevState => ({ | ||||||
| todos: [...prevState.todos, todo], | ||||||
| })); | ||||||
| } | ||||||
|
|
||||||
| <section className="main"> | ||||||
| <input type="checkbox" id="toggle-all" className="toggle-all" /> | ||||||
| <label htmlFor="toggle-all">Mark all as complete</label> | ||||||
| updateTodosToShow = (todoToShow) => { | ||||||
| this.setState({ showParam: todoToShow }); | ||||||
| } | ||||||
|
|
||||||
| <ul className="todo-list"> | ||||||
| <li> | ||||||
| <div className="view"> | ||||||
| <input type="checkbox" className="toggle" id="todo-1" /> | ||||||
| <label htmlFor="todo-1">asdfghj</label> | ||||||
| <button type="button" className="destroy" /> | ||||||
| </div> | ||||||
| <input type="text" className="edit" /> | ||||||
| </li> | ||||||
| handleRemuve = (id) => { | ||||||
| this.setState(prevState => ({ | ||||||
| todos: prevState.todos.filter(todo => ( | ||||||
| todo.id !== id | ||||||
| )), | ||||||
| })); | ||||||
| } | ||||||
|
|
||||||
| <li className="completed"> | ||||||
| <div className="view"> | ||||||
| <input type="checkbox" className="toggle" id="todo-2" /> | ||||||
| <label htmlFor="todo-2">qwertyuio</label> | ||||||
| <button type="button" className="destroy" /> | ||||||
| </div> | ||||||
| <input type="text" className="edit" /> | ||||||
| </li> | ||||||
| handleRemuveCompleted = () => { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| this.setState(prevState => ({ | ||||||
| todos: prevState.todos.filter(todo => ( | ||||||
| !todo.completed | ||||||
| )), | ||||||
| })); | ||||||
| } | ||||||
|
|
||||||
| <li className="editing"> | ||||||
| <div className="view"> | ||||||
| <input type="checkbox" className="toggle" id="todo-3" /> | ||||||
| <label htmlFor="todo-3">zxcvbnm</label> | ||||||
| <button type="button" className="destroy" /> | ||||||
| </div> | ||||||
| <input type="text" className="edit" /> | ||||||
| </li> | ||||||
| toggleComplete = (id) => { | ||||||
| this.setState(prevState => ({ | ||||||
| todos: prevState.todos.map((todo) => { | ||||||
| if (todo.id === id) { | ||||||
| return { | ||||||
| ...todo, | ||||||
| completed: !todo.completed, | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| <li> | ||||||
| <div className="view"> | ||||||
| <input type="checkbox" className="toggle" id="todo-4" /> | ||||||
| <label htmlFor="todo-4">1234567890</label> | ||||||
| <button type="button" className="destroy" /> | ||||||
| </div> | ||||||
| <input type="text" className="edit" /> | ||||||
| </li> | ||||||
| </ul> | ||||||
| </section> | ||||||
| return todo; | ||||||
| }), | ||||||
| })); | ||||||
| } | ||||||
|
|
||||||
| <footer className="footer"> | ||||||
| <span className="todo-count"> | ||||||
| 3 items left | ||||||
| </span> | ||||||
| toggleCompleteAll = () => { | ||||||
| if (this.state.todos.every(todo => (todo.completed))) { | ||||||
| this.setState(prevState => ({ | ||||||
| todos: prevState.todos.map(todo => ({ | ||||||
| ...todo, | ||||||
| completed: false, | ||||||
| })), | ||||||
| })); | ||||||
| } else { | ||||||
| this.setState(prevState => ({ | ||||||
| todos: prevState.todos.map(todo => ({ | ||||||
| ...todo, | ||||||
| completed: true, | ||||||
| })), | ||||||
| })); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| <ul className="filters"> | ||||||
| <li> | ||||||
| <a href="#/" className="selected">All</a> | ||||||
| </li> | ||||||
| render() { | ||||||
| let todoView = []; | ||||||
| const itemLeft = this.state.todos.filter(todo => ( | ||||||
| !todo.completed)).length; | ||||||
|
|
||||||
| <li> | ||||||
| <a href="#/active">Active</a> | ||||||
| </li> | ||||||
| switch (this.state.showParam) { | ||||||
| case 'active': | ||||||
| todoView = [...this.state.todos].filter(todo => ( | ||||||
| !todo.completed | ||||||
| )); | ||||||
| break; | ||||||
| case 'completed': | ||||||
| todoView = [...this.state.todos].filter(todo => ( | ||||||
| todo.completed | ||||||
| )); | ||||||
| break; | ||||||
| default: | ||||||
| todoView = [...this.state.todos]; | ||||||
| } | ||||||
|
Comment on lines
+76
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не роби це в рендері, винеси це в функцію |
||||||
|
|
||||||
| <li> | ||||||
| <a href="#/completed">Completed</a> | ||||||
| </li> | ||||||
| </ul> | ||||||
| return ( | ||||||
| <section className="todoapp"> | ||||||
| <header className="header"> | ||||||
| <h1>todos</h1> | ||||||
| <NewTodo addTodo={this.addTodo} /> | ||||||
| </header> | ||||||
|
Comment on lines
+93
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. це окремий компонент
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. То ж там одна стрічка і компонент, хіба так обов'язково робити з цього ще один компонент??? |
||||||
| {(this.state.todos.length) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. деструктуровуй стейт |
||||||
| ? ( | ||||||
| <> | ||||||
| <section className="main"> | ||||||
| <input | ||||||
| onClick={this.toggleCompleteAll} | ||||||
| checked={!itemLeft} | ||||||
| type="checkbox" | ||||||
| id="toggle-all" | ||||||
| className="toggle-all" | ||||||
| /> | ||||||
| <label htmlFor="toggle-all">Mark all as complete</label> | ||||||
|
Comment on lines
+101
to
+108
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. це в компонент Header
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Це відноситься до main |
||||||
| <TodoList | ||||||
| todos={todoView} | ||||||
| remuve={this.handleRemuve} | ||||||
| toggleComplete={this.toggleComplete} | ||||||
| /> | ||||||
| </section> | ||||||
|
|
||||||
| <button type="button" className="clear-completed"> | ||||||
| Clear completed | ||||||
| </button> | ||||||
| </footer> | ||||||
| </section> | ||||||
| ); | ||||||
| <footer className="footer"> | ||||||
| <span className="todo-count"> | ||||||
| {itemLeft} | ||||||
| item left | ||||||
| </span> | ||||||
| <TodosFilter updateTodosToShow={this.updateTodosToShow} /> | ||||||
| { | ||||||
| (this.state.todos.filter(todo => ( | ||||||
| todo.completed)).length) | ||||||
| ? ( | ||||||
| <button | ||||||
| onClick={this.handleRemuveCompleted} | ||||||
| type="button" | ||||||
| className="clear-completed" | ||||||
| > | ||||||
| Clear completed | ||||||
| </button> | ||||||
| ) | ||||||
| : ('') | ||||||
| } | ||||||
| </footer> | ||||||
|
Comment on lines
+116
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. це окремий компонент, Footer |
||||||
| </> | ||||||
| ) : ''} | ||||||
| </section> | ||||||
| ); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| export default App; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import React, { Component } from 'react'; | ||
| import './NewTodo.css'; | ||
| import PropTypes from 'prop-types'; | ||
|
|
||
| class NewTodo extends Component { | ||
| state = { | ||
| content: '', | ||
| id: 1, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. чому 1? а якщо одразу є якісь завдання? |
||
| completed: false, | ||
| } | ||
|
|
||
| handleChange = (event) => { | ||
| this.setState({ | ||
| content: event.target.value.trim(), | ||
| }); | ||
| } | ||
|
|
||
| handleSubmit = (e) => { | ||
| e.preventDefault(); | ||
|
|
||
| if (this.state.content) { | ||
| this.props.addTodo(this.state); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не передавай весь стан, передавай готове todo наверх. addTodo має приймати todo, а не весь стан
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Але якщо я хочу щоб даний компонент відповідав повністю за створення нової todo, а зверху addTodo лише додавав її в список зі всіма готовими параметрами. Чи це погана практика???
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Якщо в стейті потрібно зберігати як можна менше, тоді я перенесу id & complited у функцію що передає todo. Так добре добре буде? |
||
|
|
||
| this.setState(prevState => ({ | ||
| content: '', | ||
| id: prevState.id + 1, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. окей, тут добре) |
||
| })); | ||
| } | ||
| } | ||
|
|
||
| render() { | ||
| return ( | ||
| <form onSubmit={this.handleSubmit}> | ||
| <input | ||
| onChange={this.handleChange} | ||
| value={this.state.content} | ||
| className="new-todo" | ||
| placeholder="What needs to be done?" | ||
| /> | ||
| </form> | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| export default NewTodo; | ||
|
|
||
| NewTodo.propTypes = { | ||
| addTodo: PropTypes.func.isRequired, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
|
|
||
| export const TodoList = ({ todos, remuve, toggleComplete }) => ( | ||
| <ul className="todo-list"> | ||
| {todos.map(todo => ( | ||
| <li key={todo.id}> | ||
| <div className={todo.completed ? 'completed' : 'view'}> | ||
| <input | ||
| checked={todo.completed} | ||
| onClick={() => { | ||
| toggleComplete(todo.id); | ||
| }} | ||
| type="checkbox" | ||
| className="toggle" | ||
| id={`todo-${todo.id}`} | ||
| /> | ||
| <label htmlFor={`todo-${todo.id}`}>{todo.content}</label> | ||
| <button | ||
| onClick={() => { | ||
| remuve(todo.id); | ||
| }} | ||
| type="button" | ||
| className="destroy" | ||
| /> | ||
| </div> | ||
| <input type="text" className="edit" /> | ||
|
Comment on lines
+8
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Todo компонент, розбивай логіку на дрібніші компоненти |
||
| </li> | ||
| ))} | ||
| </ul> | ||
| ); | ||
|
|
||
| TodoList.propTypes = { | ||
| todos: PropTypes.arrayOf( | ||
| PropTypes.shape({ | ||
| content: PropTypes.string.isRequired, | ||
| id: PropTypes.number.isRequired, | ||
| completed: PropTypes.bool.isRequired, | ||
| }), | ||
| ).isRequired, | ||
| remuve: PropTypes.func.isRequired, | ||
| toggleComplete: PropTypes.func.isRequired, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import React from 'react'; | ||
| import './TodosFilter.css'; | ||
| import PropTypes from 'prop-types'; | ||
|
|
||
| export const TodosFilter = ({ updateTodosToShow }) => ( | ||
| <ul className="filters"> | ||
| <li> | ||
| <a | ||
| href="#/" | ||
| onClick={() => (updateTodosToShow('all'))} | ||
| > | ||
| All | ||
| </a> | ||
| </li> | ||
| <li> | ||
| <a | ||
| href="#/active" | ||
| onClick={() => (updateTodosToShow('active'))} | ||
| > | ||
| Active | ||
| </a> | ||
| </li> | ||
| <li> | ||
| <a | ||
| href="#/completed" | ||
| onClick={() => (updateTodosToShow('completed'))} | ||
| > | ||
| Completed | ||
| </a> | ||
| </li> | ||
|
Comment on lines
+7
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. все чим ці три фільтри відрізняються це один рядок. Ти можеш створити комонент Filter який буде приймати цей рядок і підставляти в потрібне місце, а потім через map зробити собі 3 фільтри. Коду менше буде |
||
| </ul> | ||
| ); | ||
|
|
||
| TodosFilter.propTypes = { | ||
| updateTodosToShow: PropTypes.func.isRequired, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.