-
Notifications
You must be signed in to change notification settings - Fork 2
/
App.js
122 lines (100 loc) · 3.94 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React, { Component } from 'react';
import TodoHeader from './components/todo-header';
import TodoItem from './components/todo-item';
import TodoFooter from './components/todo-footer';
import CircularLoader from './components/circular-loader';
import todosStore from './todos-store';
import { filterTodos, calculateTodosCounts } from './todos-selectors';
import './App.css';
class App extends Component {
state = {
loading: true,
error: null,
todos: null,
filter: 'all',
};
async componentDidMount() {
try {
const todos = await todosStore.load();
this.setState({ loading: false, todos });
} catch (error) {
console.error(error);
this.setState({ loading: false, error });
}
todosStore.subscribe((todos) => this.setState({ todos }));
}
render() {
const { loading, error, todos } = this.state;
return (
<div className="App">
<header className="App__header">
<h1>todos</h1>
</header>
{ loading ? this.renderLoading() : null }
{ error ? this.renderError() : null }
{ todos ? this.renderTodos() : null }
<footer className="App__footer">
<p>Double-click to edit a todo</p>
<p>Based on the work of <a href="http://github.com/petehunt/">petehunt</a></p>
<p>Slightly modified version of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
);
}
renderLoading() {
return (
<div className="App__loader">
<CircularLoader />
</div>
);
}
renderError() {
return (
<div className="App__error">
An error occurred while loading the todos
</div>
);
}
renderTodos() {
const { todos, filter } = this.state;
const todosCounts = calculateTodosCounts(todos);
const filteredTodos = filterTodos(todos, filter);
return (
<main className="App__main">
<TodoHeader
onNewTodo={ this.handleNewTodo }
isEmpty={ todosCounts.total === 0 }
allCompleted={ todosCounts.remaining === 0 }
onAllCompletedToggle={ this.handleAllCompletedToggle } />
{ filteredTodos.length ? (
<ul className="App__todo-list">
{ filteredTodos.map((todo) => (
<TodoItem
key={ todo.id }
todo={ todo }
onTitleChange={ this.handleTitleChange }
onCompleteChange={ this.handleCompleteChange }
onRemove={ this.handleRemove } />
)) }
</ul>
) : null }
{ todosCounts.total > 0 ? (
<TodoFooter
remainingCount={ todosCounts.remaining }
showClearCompleted={ todosCounts.completed > 0 }
filter={ filter }
onClearCompleted={ this.handleClearCompleted }
onFilterChange={ this.handleFilterChange } />
) : null }
</main>
);
}
handleNewTodo = (title) => todosStore.add(title);
handleAllCompletedToggle = (completed) => todosStore.updateAllCompleted(completed);
handleTitleChange = (id, title) => todosStore.updateTitle(id, title);
handleCompleteChange = (id, completed) => todosStore.updateCompleted(id, completed);
handleRemove = (id) => todosStore.remove(id);
handleClearCompleted = () => todosStore.clearCompleted();
handleFilterChange = (filter) => this.setState({ filter });
}
export default App;