Skip to content

Commit 86c8c8e

Browse files
I added a "Delete completed tasks" button in index.html
I wrote a function called deleteCompleted (toolList) for tool.mjs I wrote extra tests in todos.tes.mjs I called deleteCompleted() in script.js
1 parent 10b3ac9 commit 86c8c8e

File tree

5 files changed

+132
-59
lines changed

5 files changed

+132
-59
lines changed

Sprint-3/todo-list/index.html

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,51 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6-
<title>ToDo List</title>
7-
<link rel="stylesheet" href="style.css" />
8-
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>ToDo List</title>
7+
<link rel="stylesheet" href="style.css" />
8+
<link
9+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
10+
rel="stylesheet"
11+
/>
912

10-
<script type="module" src="script.mjs"></script>
11-
</head>
12-
<body>
13-
<div class="todo-container">
14-
<h1>My ToDo List</h1>
13+
<script type="module" src="script.mjs"></script>
14+
</head>
15+
<body>
16+
<div class="todo-container">
17+
<h1>My ToDo List</h1>
1518

16-
<div class="todo-input">
17-
<input type="text" id="new-task-input" placeholder="Enter a new task..." />
18-
<button id="add-task-btn">Add</button>
19-
</div>
19+
<div class="todo-input">
20+
<input
21+
type="text"
22+
id="new-task-input"
23+
placeholder="Enter a new task..."
24+
/>
25+
<button id="add-task-btn">Add</button>
26+
<button id="delete-completed-btn">Delete Completed Tasks</button>
27+
</div>
2028

21-
<ul id="todo-list" class="todo-list">
22-
</ul>
29+
<ul id="todo-list" class="todo-list"></ul>
2330

24-
<!--
31+
<!--
2532
This is a template for the To-do list item.
2633
It can simplify the creation of list item node in JS script.
2734
-->
28-
<template id="todo-item-template">
29-
<li class="todo-item"> <!-- include class "completed" if the task completed state is true -->
30-
<span class="description">Task description</span>
31-
<div class="actions">
32-
<button class="complete-btn"><span class="fa-solid fa-check" aria-hidden="true"></span></button>
33-
<button class="delete-btn"><span class="fa-solid fa-trash" aria-hidden="true"></span></button>
34-
</div>
35-
</li>
36-
</template>
37-
38-
</div>
39-
</body>
35+
<template id="todo-item-template">
36+
<li class="todo-item">
37+
<!-- include class "completed" if the task completed state is true -->
38+
<span class="description">Task description</span>
39+
<div class="actions">
40+
<button class="complete-btn">
41+
<span class="fa-solid fa-check" aria-hidden="true"></span>
42+
</button>
43+
<button class="delete-btn">
44+
<span class="fa-solid fa-trash" aria-hidden="true"></span>
45+
</button>
46+
</div>
47+
</li>
48+
</template>
49+
</div>
50+
</body>
4051
</html>

Sprint-3/todo-list/script.mjs

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,51 @@
1-
// Store everything imported from './todos.mjs' module as properties of an object named Todos
1+
// Store everything imported from './todos.mjs' module as properties of an object named Todos
22
import * as Todos from "./todos.mjs";
33

44
// To store the todo tasks
5-
const todos = [];
5+
let todos = [];
6+
7+
if (typeof localStorage !== "undefined") {
8+
const savedTodos = localStorage.getItem("todos");
9+
if (savedTodos) {
10+
todos = JSON.parse(savedTodos);
11+
}
12+
}
13+
14+
// Save function
15+
function saveTodos() {
16+
if (typeof localStorage !== "undefined") {
17+
localStorage.setItem("todos", JSON.stringify(todos));
18+
}
19+
}
620

721
// Set up tasks to be performed once on page load
822
window.addEventListener("load", () => {
923
document.getElementById("add-task-btn").addEventListener("click", addNewTodo);
10-
11-
// Populate sample data
12-
Todos.addTask(todos, "Wash the dishes", false);
13-
Todos.addTask(todos, "Do the shopping", true);
14-
24+
document
25+
.getElementById("delete-completed-btn")
26+
.addEventListener("click", () => {
27+
// Delete all tasks marked as completed
28+
Todos.deleteCompleted(todos);
29+
saveTodos();
30+
render();
31+
});
32+
33+
// Only populate sample data if nothing is saved`
34+
if (todos.length === 0) {
35+
Todos.addTask(todos, "Wash the dishes", false);
36+
Todos.addTask(todos, "Do the shopping", true);
37+
}
1538
render();
1639
});
1740

18-
19-
// A callback that reads the task description from an input field and
41+
// A callback that reads the task description from an input field and
2042
// append a new task to the todo list.
2143
function addNewTodo() {
2244
const taskInput = document.getElementById("new-task-input");
2345
const task = taskInput.value.trim();
2446
if (task) {
2547
Todos.addTask(todos, task, false);
48+
saveTodos();
2649
render();
2750
}
2851

@@ -45,12 +68,11 @@ function render() {
4568
});
4669
}
4770

48-
4971
// Note:
5072
// - First child of #todo-item-template is a <li> element.
5173
// We will create each ToDo list item as a clone of this node.
5274
// - This variable is declared here to be close to the only function that uses it.
53-
const todoListItemTemplate =
75+
const todoListItemTemplate =
5476
document.getElementById("todo-item-template").content.firstElementChild;
5577

5678
// Create a <li> element for the given todo task
@@ -62,15 +84,17 @@ function createListItem(todo, index) {
6284
li.classList.add("completed");
6385
}
6486

65-
li.querySelector('.complete-btn').addEventListener("click", () => {
87+
li.querySelector(".complete-btn").addEventListener("click", () => {
6688
Todos.toggleCompletedOnTask(todos, index);
89+
saveTodos();
6790
render();
6891
});
69-
70-
li.querySelector('.delete-btn').addEventListener("click", () => {
92+
93+
li.querySelector(".delete-btn").addEventListener("click", () => {
7194
Todos.deleteTask(todos, index);
95+
saveTodos();
7296
render();
7397
});
7498

7599
return li;
76-
}
100+
}

Sprint-3/todo-list/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ h1 {
3939
}
4040

4141
.todo-input button {
42-
padding: 10px 20px;
42+
padding: 10px;
4343
font-size: 16px;
44-
background-color: #4CAF50;
44+
background-color: #4caf50;
4545
color: white;
4646
border: none;
4747
border-radius: 6px;

Sprint-3/todo-list/todos.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,12 @@ export function toggleCompletedOnTask(todos, taskIndex) {
2626
if (todos[taskIndex]) {
2727
todos[taskIndex].completed = !todos[taskIndex].completed;
2828
}
29-
}
29+
}
30+
// Delete completed tasks
31+
export function deleteCompleted(todos) {
32+
for (let i = todos.length - 1; i >= 0; i--) {
33+
if (todos[i].completed) {
34+
todos.splice(i, 1);
35+
}
36+
}
37+
}

Sprint-3/todo-list/todos.test.mjs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function createMockTodos() {
1313
{ task: "Task 1 description", completed: true },
1414
{ task: "Task 2 description", completed: false },
1515
{ task: "Task 3 description", completed: true },
16-
{ task: "Task 4 description", completed: false },
16+
{ task: "Task 4 description", completed: false },
1717
];
1818
}
1919

@@ -29,7 +29,6 @@ describe("addTask()", () => {
2929
});
3030

3131
test("Should append a new task to the end of a ToDo list", () => {
32-
3332
const todos = createMockTodos();
3433
const lengthBeforeAddition = todos.length;
3534
Todos.addTask(todos, theTask.task, theTask.completed);
@@ -42,7 +41,6 @@ describe("addTask()", () => {
4241
});
4342

4443
describe("deleteTask()", () => {
45-
4644
test("Delete the first task", () => {
4745
const todos = createMockTodos();
4846
const todosBeforeDeletion = createMockTodos();
@@ -53,7 +51,7 @@ describe("deleteTask()", () => {
5351

5452
expect(todos[0]).toEqual(todosBeforeDeletion[1]);
5553
expect(todos[1]).toEqual(todosBeforeDeletion[2]);
56-
expect(todos[2]).toEqual(todosBeforeDeletion[3]);
54+
expect(todos[2]).toEqual(todosBeforeDeletion[3]);
5755
});
5856

5957
test("Delete the second task (a middle task)", () => {
@@ -66,7 +64,7 @@ describe("deleteTask()", () => {
6664

6765
expect(todos[0]).toEqual(todosBeforeDeletion[0]);
6866
expect(todos[1]).toEqual(todosBeforeDeletion[2]);
69-
expect(todos[2]).toEqual(todosBeforeDeletion[3]);
67+
expect(todos[2]).toEqual(todosBeforeDeletion[3]);
7068
});
7169

7270
test("Delete the last task", () => {
@@ -79,7 +77,7 @@ describe("deleteTask()", () => {
7977

8078
expect(todos[0]).toEqual(todosBeforeDeletion[0]);
8179
expect(todos[1]).toEqual(todosBeforeDeletion[1]);
82-
expect(todos[2]).toEqual(todosBeforeDeletion[2]);
80+
expect(todos[2]).toEqual(todosBeforeDeletion[2]);
8381
});
8482

8583
test("Delete a non-existing task", () => {
@@ -94,7 +92,6 @@ describe("deleteTask()", () => {
9492
});
9593

9694
describe("toggleCompletedOnTask()", () => {
97-
9895
test("Expect the 'completed' property to toggle on an existing task", () => {
9996
const todos = createMockTodos();
10097
const taskIndex = 1;
@@ -111,13 +108,12 @@ describe("toggleCompletedOnTask()", () => {
111108
const todos = createMockTodos();
112109
const todosBeforeToggle = createMockTodos();
113110
Todos.toggleCompletedOnTask(todos, 1);
114-
115-
expect(todos[0]).toEqual(todosBeforeToggle[0]);
111+
112+
expect(todos[0]).toEqual(todosBeforeToggle[0]);
116113
expect(todos[2]).toEqual(todosBeforeToggle[2]);
117114
expect(todos[3]).toEqual(todosBeforeToggle[3]);
118115
});
119116

120-
121117
test("Expect no change when toggling on a non-existing task", () => {
122118
const todos = createMockTodos();
123119
const todosBeforeToggle = createMockTodos();
@@ -130,3 +126,37 @@ describe("toggleCompletedOnTask()", () => {
130126
});
131127
});
132128

129+
describe("deleteCompleted()", () => {
130+
test("Expect all completed tasks to be deleted", () => {
131+
const todos = createMockTodos();
132+
Todos.deleteCompleted(todos);
133+
134+
expect(todos).toHaveLength(2);
135+
expect(todos[0]).toEqual({ task: "Task 2 description", completed: false });
136+
expect(todos[1]).toEqual({ task: "Task 4 description", completed: false });
137+
});
138+
139+
test("Expect no change if there is no completed task", () => {
140+
const todos = [
141+
{ task: "Task A description", completed: false },
142+
{ task: "Task B description", completed: false },
143+
];
144+
const todosBeforeDeletion = [
145+
{ task: "Task A description", completed: false },
146+
{ task: "Task B description", completed: false },
147+
];
148+
149+
Todos.deleteCompleted(todos);
150+
expect(todos).toEqual(todosBeforeDeletion);
151+
});
152+
153+
test("Expect all tasks to be deleted if all tasks are completed", () => {
154+
const todos = [
155+
{ task: "Task A description", completed: true },
156+
{ task: "Task B description", completed: true },
157+
];
158+
159+
Todos.deleteCompleted(todos);
160+
expect(todos).toHaveLength(0);
161+
});
162+
});

0 commit comments

Comments
 (0)