Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# React ToDo App
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://<your_account>.github.io/react_todo-app/)
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://alenaloik.github.io/react_todo-app/)
- Follow the [React task guideline](https://github.com/mate-academy/react_task-guideline#react-tasks-guideline)

## Description
Expand Down
241 changes: 160 additions & 81 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,85 +1,164 @@
import React from 'react';

function App() {
return (
<section className="todoapp">
<header className="header">
<h1>todos</h1>

<input
className="new-todo"
placeholder="What needs to be done?"
/>
</header>

<section className="main">
<input type="checkbox" id="toggle-all" className="toggle-all" />
<label htmlFor="toggle-all">Mark all as complete</label>

<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>

<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>

<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>

<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>
import React, { Component } from 'react';
import TodoList from './components/TodoList/TodoList';
import { Footer } from './components/Footer/Footer';
import { Header } from './components/Header/Header';

class App extends Component {
state = {
todos: [],
showParam: 'all',
};

addTodo = (todo) => {
this.setState(prevState => ({
todos: [...prevState.todos, todo],
}));
}

updateTodosToShow = (todoToShow) => {
this.setState({ showParam: todoToShow });
}

handleRemove = (id) => {
this.setState(prevState => ({
todos: prevState.todos.filter(todo => (
todo.id !== id
)),
}));
}

handleDobleClick = ({ id }) => {
this.setState(prevState => ({
todos: prevState.todos.map(todo => (
(todo.id !== id) ? ({
...todo, editing: false,
}) : ({
...todo, editing: true,
})
)),
}));
}

editTodo = (content) => {
if (content) {
this.setState(prevState => ({
todos: prevState.todos.map(todo => (
(todo.editing) ? ({
...todo, content,
}) : todo)),
}));
} else {
this.setState(prevState => ({
todos: prevState.todos.filter(todo => (
!todo.editing
)),
}));
}
}

handleRemoveCompleted = () => {
this.setState(prevState => ({
todos: prevState.todos.filter(todo => (
!todo.completed
)),
}));
}

<footer className="footer">
<span className="todo-count">
3 items left
</span>

<ul className="filters">
<li>
<a href="#/" className="selected">All</a>
</li>

<li>
<a href="#/active">Active</a>
</li>

<li>
<a href="#/completed">Completed</a>
</li>
</ul>

<button type="button" className="clear-completed">
Clear completed
</button>
</footer>
</section>
);
toggleComplete = (id) => {
this.setState(prevState => ({
todos: prevState.todos.map((todo) => {
if (todo.id === id) {
return {
...todo,
completed: !todo.completed,
};
}

return todo;
}),
}));
}

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,
})),
}));
}
}

getTodos = (status) => {
let todoView = [];
const { todos } = this.state;

switch (status) {
case 'active':
todoView = todos.filter(todo => (
!todo.completed
));
break;
case 'completed':
todoView = todos.filter(todo => (
todo.completed
));
break;
default:
todoView = todos;
}

return todoView;
}

render() {
const { todos, showParam } = this.state;
const todoView = this.getTodos(showParam);
const itemLeft = todos.filter(todo => (
!todo.completed)).length;

return (
<section className="todoapp">
<Header addTodo={this.addTodo} />
{(todos.length)
? (
<>
<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>
<TodoList
todos={todoView}
remove={this.handleRemove}
toggleComplete={this.toggleComplete}
handleDobleClick={this.handleDobleClick}
editTodo={this.editTodo}
/>
</section>
<Footer
itemLeft={itemLeft}
todos={todos}
updateTodosToShow={this.updateTodosToShow}
handleRemoveCompleted={this.handleRemoveCompleted}
/>
</>
) : ''}
</section>
);
}
}

export default App;
Empty file.
46 changes: 46 additions & 0 deletions src/components/Footer/Footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import './Footer.css';
import PropTypes from 'prop-types';
import { TodosFilter } from '../TodosFilter/TodosFilter';

export const Footer = ({
todos,
updateTodosToShow,
handleRemoveCompleted,
itemLeft,
}) => (
<footer className="footer">
<span className="todo-count">
{itemLeft}
{' '}
item left
</span>
<TodosFilter updateTodosToShow={updateTodosToShow} />
{
(todos.filter(todo => (todo.completed)).length)
? (
<button
onClick={handleRemoveCompleted}
type="button"
className="clear-completed"
>
Clear completed
</button>
)
: ('')
}
</footer>
);

Footer.propTypes = {
todos: PropTypes.arrayOf(
PropTypes.shape({
content: PropTypes.string.isRequired,
id: PropTypes.number.isRequired,
completed: PropTypes.bool.isRequired,
}),
).isRequired,
updateTodosToShow: PropTypes.func.isRequired,
handleRemoveCompleted: PropTypes.func.isRequired,
itemLeft: PropTypes.number.isRequired,
};
Empty file.
15 changes: 15 additions & 0 deletions src/components/Header/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import './Header.css';
import PropTypes from 'prop-types';
import NewTodo from '../NewTodo/NewTodo';

export const Header = ({ addTodo }) => (
<header className="header">
<h1>todos</h1>
<NewTodo addTodo={addTodo} />
</header>
);

Header.propTypes = {
addTodo: PropTypes.func.isRequired,
};
Empty file.
52 changes: 52 additions & 0 deletions src/components/NewTodo/NewTodo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { Component } from 'react';
import './NewTodo.css';
import PropTypes from 'prop-types';

class NewTodo extends Component {
state = {
content: '',
}

handleChange = (event) => {
this.setState({
content: event.target.value.trim(),
});
}

handleSubmit = (e) => {
e.preventDefault();
const { content } = this.state;
const id = +Date.now();
const completed = false;
const todo = {
content, id, completed,
};

if (content) {
this.props.addTodo(todo);

this.setState(prevState => ({
content: '',
}));
}
}

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,
};
Empty file.
Loading