diff --git a/step1-06/src/App.tsx b/step1-06/src/TodoApp.tsx similarity index 62% rename from step1-06/src/App.tsx rename to step1-06/src/TodoApp.tsx index 3f19668..b0dbfba 100644 --- a/step1-06/src/App.tsx +++ b/step1-06/src/TodoApp.tsx @@ -7,12 +7,24 @@ export class TodoApp extends React.Component { constructor(props) { super(props); this.state = { - todos: [ - { key: 1, text: 'Todo 1', completed: true }, - { key: 2, text: 'Todo 2' }, - { key: 3, text: 'Todo 3' }, - { key: 4, text: 'Todo 4' } - ], + todos: { + '04': { + label: 'Todo 4', + completed: true + }, + '03': { + label: 'Todo 3', + completed: false + }, + '02': { + label: 'Todo 2', + completed: false + }, + '01': { + label: 'Todo 1', + completed: false + } + }, filter: 'all' }; } diff --git a/step1-06/src/components/TodoFooter.tsx b/step1-06/src/components/TodoFooter.tsx index 53417df..888118f 100644 --- a/step1-06/src/components/TodoFooter.tsx +++ b/step1-06/src/components/TodoFooter.tsx @@ -1,10 +1,12 @@ -import React from "react"; +import React from 'react'; export const TodoFooter = (props: any) => { - const items = props.todos.filter(todo => !todo.completed) + const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length; return ( ); diff --git a/step1-06/src/components/TodoHeader.tsx b/step1-06/src/components/TodoHeader.tsx index 11787c5..9d31542 100644 --- a/step1-06/src/components/TodoHeader.tsx +++ b/step1-06/src/components/TodoHeader.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export class TodoHeader extends React.Component { render() { @@ -9,11 +9,9 @@ export class TodoHeader extends React.Component {
- - - + + +
); diff --git a/step1-06/src/components/TodoList.tsx b/step1-06/src/components/TodoList.tsx index 8fb047a..a92faa0 100644 --- a/step1-06/src/components/TodoList.tsx +++ b/step1-06/src/components/TodoList.tsx @@ -4,24 +4,15 @@ import { TodoListItem } from './TodoListItem'; export class TodoList extends React.Component { render() { const { filter, todos } = this.props; - let filteredTodos: typeof todos = {}; - - filteredTodos = todos.filter(todo => { - const matchesActive = filter == 'active' && !todo.completed; - const matchesCompleted = filter == 'completed' && todo.completed; - - return filter == 'all' || matchesActive || matchesCompleted; - }) - - const TodoListItems = filteredTodos.map(todo => { - return ( - - ); - }) + const filteredTodos = Object.keys(todos).filter(id => { + return filter === 'all' || (filter === 'completed' && todos[id].completed) || (filter === 'active' && !todos[id].completed); + }); return (
    - {TodoListItems} + {filteredTodos.map(id => ( + + ))}
); } diff --git a/step1-06/src/components/TodoListItem.tsx b/step1-06/src/components/TodoListItem.tsx index 29db423..4dbf2ae 100644 --- a/step1-06/src/components/TodoListItem.tsx +++ b/step1-06/src/components/TodoListItem.tsx @@ -1,13 +1,12 @@ -import React from "react"; +import React from 'react'; export class TodoListItem extends React.Component { - render() { - const {text, completed} = this.props; + const { label, completed } = this.props; return (
  • ); diff --git a/step1-06/src/index.tsx b/step1-06/src/index.tsx index 3289ec8..ccf63e2 100644 --- a/step1-06/src/index.tsx +++ b/step1-06/src/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import { TodoApp } from "./App"; -ReactDOM.render(, document.getElementById("app")); +import React from 'react'; +import ReactDOM from 'react-dom'; +import { TodoApp } from './TodoApp'; +ReactDOM.render(, document.getElementById('app')); diff --git a/step1-07/src/App.tsx b/step1-07/src/App.tsx deleted file mode 100644 index e7679f6..0000000 --- a/step1-07/src/App.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from "react"; -import { TodoFooter } from "./components/TodoFooter"; -import { TodoHeader } from "./components/TodoHeader"; -import { TodoList } from "./components/TodoList"; - -export class TodoApp extends React.Component { - constructor(props) { - super(props); - this.state = { - inputValue: "", - todos: [], - filter: "all" - }; - } - render() { - const { filter, todos, inputValue } = this.state; - return ( -
    - - - -
    - ); - } - - _addTodo = () => { - const { todos, inputValue } = this.state; - const newTodos = [ - { - id: todos[0] ? todos[0].id + 1 : 0, - text: inputValue - }, - ...todos - ]; - - this.setState({ - todos: newTodos, - inputValue: "" - }); - }; - - _toggleTodoComplete = (id) => { - this.setState({ - todos: this.state.todos.map(todo => { - if (todo.id == id) {todo.completed = !todo.completed} - return todo; - }) - }) - } - - _removeCompletedTodos = () => { - this.setState({ - todos: this.state.todos.filter(todo => { - return !todo.completed; - }) - }) - } - - _updateFilter = (filter) => { - this.setState({ - filter: filter - }) - }; - - _updateInput = ev => { - this.setState({ - inputValue: ev.target.value - }); - }; -} diff --git a/step1-07/src/TodoApp.tsx b/step1-07/src/TodoApp.tsx new file mode 100644 index 0000000..34f81b7 --- /dev/null +++ b/step1-07/src/TodoApp.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { TodoFooter } from './components/TodoFooter'; +import { TodoHeader } from './components/TodoHeader'; +import { TodoList } from './components/TodoList'; + +let index = 0; + +export class TodoApp extends React.Component { + constructor(props) { + super(props); + this.state = { + todos: {}, + filter: 'all' + }; + } + + render() { + const { filter, todos } = this.state; + return ( +
    + + + +
    + ); + } + + private _addTodo = label => { + const { todos } = this.state; + const id = index++; + + this.setState({ + todos: { ...todos, [id]: { label, completed: false } } + }); + }; + + private _remove = id => { + const newTodos = { ...this.state.todos }; + delete newTodos[id]; + + this.setState({ + todos: newTodos + }); + }; + + private _complete = id => { + const newTodos = { ...this.state.todos }; + newTodos[id].completed = !newTodos[id].completed; + + this.setState({ + todos: newTodos + }); + }; + + private _edit = (id, label) => { + const newTodos = { ...this.state.todos }; + newTodos[id] = { ...newTodos[id], label }; + + this.setState({ + todos: newTodos + }); + }; + + private _clear = () => { + const { todos } = this.state; + const newTodos = {}; + + Object.keys(this.state.todos).forEach(id => { + if (!todos[id].completed) { + newTodos[id] = todos[id]; + } + }); + + this.setState({ + todos: newTodos + }); + }; + + private _setFilter = filter => { + this.setState({ + filter: filter + }); + }; +} diff --git a/step1-07/src/components/TodoFooter.tsx b/step1-07/src/components/TodoFooter.tsx index 78b3247..b36b788 100644 --- a/step1-07/src/components/TodoFooter.tsx +++ b/step1-07/src/components/TodoFooter.tsx @@ -1,11 +1,15 @@ -import React from "react"; +import React from 'react'; export const TodoFooter = (props: any) => { - const items = props.todos.filter(todo => !todo.completed) + const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length; return (
    - {items.length} items left - + + {itemCount} item{itemCount > 1 ? 's' : ''} left + +
    ); }; diff --git a/step1-07/src/components/TodoHeader.tsx b/step1-07/src/components/TodoHeader.tsx index e9fc0d1..f3b2b35 100644 --- a/step1-07/src/components/TodoHeader.tsx +++ b/step1-07/src/components/TodoHeader.tsx @@ -1,21 +1,45 @@ -import React from "react"; +import React from 'react'; export class TodoHeader extends React.Component { + constructor(props) { + super(props); + this.state = { labelInput: '' }; + } + render() { - const { filter, inputValue, onInputChange, onTodoSubmit, onFilterClick } = this.props; + const { filter } = this.props; return (

    todos

    - - + +
    - - - + +
    ); } + + _onFilter = filter => { + this.props.setFilter(filter); + }; + + _onChange = evt => { + this.setState({ labelInput: evt.target.value }); + }; + + _onAdd = () => { + this.props.addTodo(this.state.labelInput); + this.setState({ labelInput: '' }); + }; } diff --git a/step1-07/src/components/TodoList.tsx b/step1-07/src/components/TodoList.tsx index 2989ff2..d5c83a2 100644 --- a/step1-07/src/components/TodoList.tsx +++ b/step1-07/src/components/TodoList.tsx @@ -3,25 +3,17 @@ import { TodoListItem } from './TodoListItem'; export class TodoList extends React.Component { render() { - const { filter, todos, onTodoToggle } = this.props; - let filteredTodos: typeof todos = {}; + const { filter, todos, complete } = this.props; - filteredTodos = todos.filter(todo => { - const matchesActive = filter == 'active' && !todo.completed; - const matchesCompleted = filter == 'completed' && todo.completed; - - return filter == 'all' || matchesActive || matchesCompleted; - }) - - const TodoListItems = filteredTodos.map((todo) => { - return ( - - ); - }) + const filteredTodos = Object.keys(todos).filter(id => { + return filter === 'all' || (filter === 'completed' && todos[id].completed) || (filter === 'active' && !todos[id].completed); + }); return (
      - {TodoListItems} + {filteredTodos.map(id => ( + + ))}
    ); } diff --git a/step1-07/src/components/TodoListItem.tsx b/step1-07/src/components/TodoListItem.tsx index 98424f9..a927e63 100644 --- a/step1-07/src/components/TodoListItem.tsx +++ b/step1-07/src/components/TodoListItem.tsx @@ -1,13 +1,13 @@ -import React from "react"; +import React from 'react'; export class TodoListItem extends React.Component { - render() { - const {text, completed, onTodoToggle, id} = this.props; + const { label, completed, complete, id } = this.props; + return (
  • ); diff --git a/step1-07/src/index.tsx b/step1-07/src/index.tsx index 3289ec8..ccf63e2 100644 --- a/step1-07/src/index.tsx +++ b/step1-07/src/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import { TodoApp } from "./App"; -ReactDOM.render(, document.getElementById("app")); +import React from 'react'; +import ReactDOM from 'react-dom'; +import { TodoApp } from './TodoApp'; +ReactDOM.render(, document.getElementById('app'));