Skip to content

Commit fc05b25

Browse files
authored
Merge pull request #11 from ink-0/week1/10/TodoFilter
Week1/10/todo filter
2 parents e1c0dbc + b4e07a0 commit fc05b25

File tree

8 files changed

+158
-142
lines changed

8 files changed

+158
-142
lines changed

index.html

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,56 +15,8 @@
1515
<body>
1616
<div class="todoapp">
1717
<h1>TODOS</h1>
18-
19-
<!-- <input
20-
id="new-todo-title"
21-
class="new-todo"
22-
placeholder="할일을 추가해주세요"
23-
autofocus
24-
/> -->
2518
<main class="App">
2619
<input class="toggle-all" type="checkbox" />
27-
<!-- <ul id="todo-list" class="todo-list"></ul> -->
28-
<!-- <div class="count-container"> -->
29-
<!-- <span class="todo-count">총 <strong>0</strong> 개</span> -->
30-
<!-- <ul class="filters">
31-
<li>
32-
<a class="all selected" href="#">전체보기</a>
33-
</li>
34-
<li>
35-
<a class="active" href="#active">해야할 일</a>
36-
</li>
37-
<li>
38-
<a class="completed" href="#completed">완료한 일</a>
39-
</li>
40-
</ul> -->
41-
</div>
42-
<!-- <ul id="todo-list" class="todo-list">
43-
<li>
44-
<div class="view">
45-
<input class="toggle" type="checkbox"/>
46-
<label class="label">새로운 타이틀</label>
47-
<button class="destroy"></button>
48-
</div>
49-
<input class="edit" value="새로운 타이틀" />
50-
</li>
51-
<li class="editing">
52-
<div class="view">
53-
<input class="toggle" type="checkbox" />
54-
<label class="label">완료된 타이틀</label>
55-
<button class="destroy"></button>
56-
</div>
57-
<input class="edit" value="완료된 타이틀" />
58-
</li>
59-
<li class="completed">
60-
<div class="view">
61-
<input class="toggle" type="checkbox" checked/>
62-
<label class="label">완료된 타이틀</label>
63-
<button class="destroy"></button>
64-
</div>
65-
<input class="edit" value="완료된 타이틀" />
66-
</li>
67-
</ul> -->
6820
</main>
6921
</div>
7022
</body>

src/js/TodoApp.js

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import TodoCount from './TodoCount.js';
2-
import TodoInput from './TodoInput.js';
3-
import TodoList from './TodoList.js';
1+
import TodoFilter from './components/TodoFilter.js';
2+
import TodoInput from './components/TodoInput.js';
3+
import TodoList from './components/TodoList.js';
4+
import { FILTER_TYPES } from '../utils/const.js';
45

56
export default function TodoApp($app) {
67
this.state = {
@@ -16,31 +17,35 @@ export default function TodoApp($app) {
1617
state: '',
1718
},
1819
],
20+
todoesFiltered: [],
21+
isFilter: false,
22+
todoesCount: '0',
1923
};
2024

2125
this.setState = (nextState) => {
2226
this.state = nextState;
23-
todoList.setState(this.state.todoes);
24-
todoCount.setState(this.state.todoes);
25-
todoInput.setState(this.state.todoes);
27+
todoList.setState(nextState);
28+
todoInput.setState(nextState);
29+
todoFilter.setState(nextState);
2630
};
2731

2832
const todoInput = new TodoInput({
2933
$app,
30-
initialState: this.state.todoes,
34+
initialState: this.state,
3135
onAdd: (contents) => addTodo(contents),
3236
});
3337

3438
const todoList = new TodoList({
3539
$app,
36-
initialState: this.state.todoes,
40+
initialState: this.state,
3741
onToggle: (idx) => toggleTodo(idx),
3842
onDelete: (idx) => deleteTodo(idx),
3943
onEdit: (idx, isEdit, newContent) => editTodo(idx, isEdit, newContent),
4044
});
41-
const todoCount = new TodoCount({
45+
const todoFilter = new TodoFilter({
4246
$app,
43-
initialState: this.state.count,
47+
initialState: this.state,
48+
onFilter: (filterType) => filterTodo(filterType),
4449
});
4550

4651
const init = () => {
@@ -50,27 +55,28 @@ export default function TodoApp($app) {
5055
};
5156
init();
5257

53-
const addTodo = (contents) => {
54-
const todos = this.state.todoes;
55-
const nextIdx = Math.max(0, ...todos.map((todo) => todo.idx)) + 1;
58+
const addTodo = (addContent) => {
59+
const { todoes } = this.state;
60+
const nextIdx = Math.max(0, ...todoes.map((todo) => todo.idx)) + 1;
5661
const newTodo = {
5762
idx: nextIdx,
58-
content: contents,
63+
content: addContent,
5964
state: '',
6065
edit: '',
6166
};
62-
this.state.todoes.push(newTodo);
67+
todoes.push(newTodo);
6368

6469
this.setState({
6570
...this.state,
6671
});
6772
};
6873

6974
const toggleTodo = (idx) => {
70-
const todos = this.state.todoes;
71-
todos.map((todo) => {
75+
const { todoes } = this.state;
76+
77+
todoes.map((todo) => {
7278
if (todo.idx === idx) {
73-
todo.state = todo.state === '' ? 'completed' : '';
79+
todo.state = todo.state === '' ? FILTER_TYPES.COMPLETE : '';
7480
}
7581
});
7682
this.setState({
@@ -79,19 +85,21 @@ export default function TodoApp($app) {
7985
};
8086

8187
const deleteTodo = (idx) => {
82-
const todos = this.state.todoes;
83-
const newTodos = todos.filter((todo) => {
88+
const { todoes } = this.state;
89+
90+
const resetTodoes = todoes.filter((todo) => {
8491
return todo.idx !== idx;
8592
});
8693

8794
this.setState({
88-
todoes: newTodos,
95+
todoes: resetTodoes,
8996
});
9097
};
9198

9299
const editTodo = (idx, isEdit, newContent) => {
93-
const todos = this.state.todoes;
94-
todos.map((todo) => {
100+
const { todoes } = this.state;
101+
102+
todoes.map((todo) => {
95103
if (todo.idx === idx) {
96104
todo.state = todo.state === '' ? 'editing' : '';
97105
if (isEdit) {
@@ -103,4 +111,37 @@ export default function TodoApp($app) {
103111
...this.state,
104112
});
105113
};
114+
115+
const filterTodo = (filterType) => {
116+
const { todoes } = this.state;
117+
118+
if (filterType === FILTER_TYPES.ALL) {
119+
this.setState({
120+
...this.state,
121+
isFilter: false,
122+
todoesCount: todoes.length,
123+
});
124+
} else if (filterType === FILTER_TYPES.COMPLETE) {
125+
const completedTodoes = todoes.filter(
126+
(todo) => todo.state === FILTER_TYPES.COMPLETE
127+
);
128+
129+
this.setState({
130+
...this.state,
131+
todoesFiltered: completedTodoes,
132+
isFilter: true,
133+
todoesCount: completedTodoes.length,
134+
});
135+
} else if (filterType === FILTER_TYPES.ACTIVE) {
136+
const activeTodoes = todoes.filter(
137+
(todo) => todo.state !== FILTER_TYPES.COMPLETE
138+
);
139+
this.setState({
140+
...this.state,
141+
todoesFiltered: activeTodoes,
142+
isFilter: true,
143+
todoesCount: activeTodoes.length,
144+
});
145+
}
146+
};
106147
}

src/js/TodoCount.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/js/TodoItem.js

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/js/components/TodoFilter.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { FILTER_TYPES, TODO_FILTER_MENU } from '../../utils/const.js';
2+
export default function TodoFilter({ $app, initialState, onFilter }) {
3+
this.state = initialState;
4+
5+
this.$target = document.createElement('div');
6+
this.$target.className = 'count-container';
7+
$app.appendChild(this.$target);
8+
const $nodeTodoFilter = this.$target;
9+
10+
this.setState = (nextState) => {
11+
this.state = nextState;
12+
this.render();
13+
};
14+
15+
$nodeTodoFilter.addEventListener('click', (e) => {
16+
const $node = e.target;
17+
18+
if ($node.className === FILTER_TYPES.COMPLETE) {
19+
onFilter(FILTER_TYPES.COMPLETE);
20+
} else if ($node.className === FILTER_TYPES.ACTIVE) {
21+
onFilter(FILTER_TYPES.ACTIVE);
22+
} else {
23+
onFilter(FILTER_TYPES.ALL);
24+
}
25+
});
26+
27+
this.render = () => {
28+
const { todoes, isFilter, todoesFiltered } = this.state;
29+
30+
const todoTotalCount = isFilter ? todoesFiltered.length : todoes.length;
31+
const todoFilterTemplate = `
32+
<span class="todo-count">총 <strong>${todoTotalCount}</strong> 개</span>
33+
<ul class="filters">
34+
<li>
35+
<a class=${FILTER_TYPES.ALL} href="#">${TODO_FILTER_MENU.ALL_MENU}</a>
36+
</li>
37+
<li>
38+
<a class=${FILTER_TYPES.ACTIVE} href="#${FILTER_TYPES.ACTIVE}">${TODO_FILTER_MENU.ACTIVE_MENU}</a>
39+
</li>
40+
<li>
41+
<a class="completed" href="#${FILTER_TYPES.COMPLETE}">${TODO_FILTER_MENU.COMPLETE_MENU}</a>
42+
</li>
43+
</ul>`;
44+
$nodeTodoFilter.innerHTML = todoFilterTemplate;
45+
};
46+
}
File renamed without changes.

0 commit comments

Comments
 (0)