Skip to content

Commit 90adc4b

Browse files
committed
feat: TodoList 컴포넌트 클래스 + ts 변환
1 parent ebc2683 commit 90adc4b

File tree

3 files changed

+58
-53
lines changed

3 files changed

+58
-53
lines changed

src/App.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { setItem } from "./utils/storage.js";
66
import { TodoCount as TodoCnt, TodoItem } from "./types/todo.js";
77

88
export default class App {
9-
// todoList: TodoList;
9+
todoList: TodoList;
1010
// todoCount: TodoCount;
1111

1212
constructor(
@@ -24,11 +24,11 @@ export default class App {
2424
// },
2525
// });
2626

27-
// this.todoList = new TodoList({
28-
// $target: this.$target,
29-
// initialState: this.initialState,
30-
// updateCount: (state: TodoItem[]) => this.updateCount(state),
31-
// });
27+
this.todoList = new TodoList(
28+
this.$target,
29+
this.initialState,
30+
(state: TodoItem[]) => this.updateCount(state)
31+
);
3232

3333
// this.todoCount = new TodoCount({
3434
// $target: this.$target,
@@ -37,10 +37,10 @@ export default class App {
3737
}
3838

3939
// 카운트 업데이트
40-
// updateCount(todoList: TodoItem[]) {
41-
// const done = todoList.filter((todo) => todo.isCompleted).length;
42-
// const nextState = { total: todoList.length, done };
43-
// this.todoCount.setState(nextState);
44-
// setItem("count", JSON.stringify(nextState));
45-
// };
40+
updateCount(todoList: TodoItem[]) {
41+
// const done = todoList.filter((todo) => todo.isCompleted).length;
42+
// const nextState = { total: todoList.length, done };
43+
// this.todoCount.setState(nextState);
44+
// setItem("count", JSON.stringify(nextState));
45+
};
4646
}

src/components/TodoList.ts

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,58 @@
11
import { setItem } from "../utils/storage.js";
22
import validation from "../utils/validation.js";
3+
import { TodoItem } from "../types/todo.js";
34

4-
// params.$target - 해당 컴포넌트가 추가될 DOM 앨리먼트
5-
// params.initialState - 해당 컴포넌트의 초기 상태
6-
export default function TodoList({ $target, initialState, updateCount }) {
7-
validation.newTarget(new.target);
5+
export default class TodoList {
6+
state: TodoItem[] = [];
7+
$todoList = document.createElement("div");
88

9-
const $todoList = document.createElement("div");
10-
$target.appendChild($todoList);
9+
constructor(
10+
private readonly $target: HTMLElement,
11+
private readonly initialState: TodoItem[],
12+
private readonly updateCount: (state: TodoItem[]) => void
13+
) {
14+
this.$target.appendChild(this.$todoList);
1115

12-
if (Array.isArray(initialState)) this.state = initialState;
13-
else this.state = [];
16+
if (Array.isArray(this.initialState)) this.state = this.initialState;
17+
else this.state = [];
1418

15-
this.setState = (nextState) => {
19+
this.render();
20+
21+
this.$todoList.addEventListener("click", (e) => {
22+
const target = e.target as HTMLLIElement;
23+
const $li = target.closest("li");
24+
25+
if ($li) {
26+
const newState = [...this.state];
27+
const index = +($li.dataset.index as string);
28+
29+
if (target.className === "deleteBtn") {
30+
newState.splice(index, 1);
31+
this.setState(newState);
32+
} else if (target.className.includes("todoList")) {
33+
const isCompleted = target.className.includes("completed");
34+
if (isCompleted) target.classList.remove("completed");
35+
else target.classList.add("completed");
36+
newState[index] = {
37+
...newState[index],
38+
isCompleted: !isCompleted,
39+
};
40+
this.setState(newState);
41+
}
42+
}
43+
});
44+
}
45+
46+
setState(nextState: TodoItem[]) {
1647
const newState = validation.state(nextState);
1748
this.state = newState;
1849
setItem("todo", JSON.stringify(newState));
19-
updateCount(newState);
50+
this.updateCount(newState);
2051
this.render();
2152
};
2253

23-
this.render = () => {
24-
$todoList.innerHTML = `
54+
render() {
55+
this.$todoList.innerHTML = `
2556
<ul>
2657
${this.state
2758
.map(
@@ -37,32 +68,4 @@ export default function TodoList({ $target, initialState, updateCount }) {
3768
</ul>
3869
`;
3970
};
40-
41-
$todoList.addEventListener("click", (e) => {
42-
const { target } = e;
43-
const $li = target.closest("li");
44-
45-
if ($li) {
46-
const newState = [...this.state];
47-
const { index } = $li.dataset;
48-
49-
if (target.className === "deleteBtn") {
50-
newState.splice(index, 1);
51-
this.setState(newState);
52-
} else if (target.className.includes("todoList")) {
53-
const isCompleted = target.className.includes("completed");
54-
55-
if (isCompleted) target.classList.remove("completed");
56-
else target.classList.add("completed");
57-
58-
newState[index] = {
59-
...newState[index],
60-
isCompleted: !isCompleted,
61-
};
62-
this.setState(newState);
63-
}
64-
}
65-
});
66-
67-
this.render();
6871
}

src/utils/validation.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { TodoItem } from "../types/todo.js";
2+
13
const validation = {
24
newTarget(target) {
35
if (!target) {
46
throw new Error("You must use new keyword");
57
}
68
},
7-
state(todoList) {
9+
state(todoList: TodoItem[]) {
810
return todoList.filter(
911
(todo) =>
1012
typeof todo?.text === "string" && typeof todo?.isCompleted === "boolean"

0 commit comments

Comments
 (0)