Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 42 additions & 37 deletions Sprint-3/todo-list/index.html
Original file line number Diff line number Diff line change
@@ -1,40 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>ToDo List</title>
<link rel="stylesheet" href="style.css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">

<script type="module" src="script.mjs"></script>
</head>
<body>
<div class="todo-container">
<h1>My ToDo List</h1>

<div class="todo-input">
<input type="text" id="new-task-input" placeholder="Enter a new task..." />
<button id="add-task-btn">Add</button>
</div>

<ul id="todo-list" class="todo-list">
</ul>

<!--
This is a template for the To-do list item.
It can simplify the creation of list item node in JS script.
-->
<template id="todo-item-template">
<li class="todo-item"> <!-- include class "completed" if the task completed state is true -->
<span class="description">Task description</span>
<div class="actions">
<button class="complete-btn"><span class="fa-solid fa-check" aria-hidden="true"></span></button>
<button class="delete-btn"><span class="fa-solid fa-trash" aria-hidden="true"></span></button>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>To Do List App</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
</head>
<body>
<div class="todo-container">
<form onsubmit="addNewTodo(event)" id="todo-form">
<div>
<input
id="todoInput"
type="text"
placeholder="New todo..."
class="form-control"
/>
</div>
<div>
<button type="button" id="add-btn" class="btn btn-primary mt-2">
Add Todo
</button>
<button
type="button"
id="remove-all-completed"
class="btn btn-danger mt-2"
>
Remove all completed
</button>
</div>
</li>
</template>

</div>
</body>
</html>
</form>
<ul id="todo-list" class="list-group mt-3"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
84 changes: 84 additions & 0 deletions Sprint-3/todo-list/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
function toggleTodoCompletion(todo) {
todo.completed = !todo.completed;
}

function removeTodo(todos, todo) {
return todos.filter((t) => t !== todo);
}
Comment on lines +5 to +7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.filter() creates a new array. The original todos[] is not updated accordingly.


function deleteAllCompletedTodos() {
todos = todos.filter((todo) => !todo.completed);
populateTodoList(todos);
}

function createTodoElement(todo, todos) {
let li = document.createElement("li");
li.textContent = todo.task;
li.className = `list-group-item ${todo.completed ? "completed" : ""}`;

let span = document.createElement("span");
span.className = "badge bg-light rounded-pill";

let checkIcon = document.createElement("i");
checkIcon.className = "fa fa-check todo-icon";
checkIcon.setAttribute("aria-hidden", "true");
checkIcon.addEventListener("click", () => {
toggleTodoCompletion(todo);
li.classList.toggle("completed");
});

let trashIcon = document.createElement("i");
trashIcon.className = "fa fa-trash todo-icon";
trashIcon.setAttribute("aria-hidden", "true");
trashIcon.addEventListener("click", () => {
todos = removeTodo(todos, todo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 34 only assigns an array to the local variable todos; it does not change the array passed to this function.

populateTodoList(todos);
});

span.appendChild(checkIcon);
span.appendChild(trashIcon);
li.appendChild(span);

return li;
}

function populateTodoList(todos) {
let list = document.getElementById("todo-list");
list.innerHTML = "";
todos.forEach((todo) => {
list.appendChild(createTodoElement(todo, todos));
});
}

let todos = [
{ task: "Wash the dishes", completed: false },
{ task: "Do the shopping", completed: false },
];

function addNewTodo(event) {
event.preventDefault();
let input = document.getElementById("todoInput");
let newTask = input.value.trim();

if (newTask === "") {
alert("Input field cannot be empty.");
return;
}

if (/[^A-Za-z\s]/.test(newTask)) {
alert("Please enter letters and spaces only.");
input.value = "";
return;
}

todos.push({ task: newTask, completed: false });
populateTodoList(todos);
input.value = "";
}

document.getElementById("add-btn").addEventListener("click", addNewTodo);
document
.getElementById("remove-all-completed")
.addEventListener("click", deleteAllCompletedTodos);

populateTodoList(todos);
76 changes: 0 additions & 76 deletions Sprint-3/todo-list/script.mjs

This file was deleted.

124 changes: 41 additions & 83 deletions Sprint-3/todo-list/style.css
Original file line number Diff line number Diff line change
@@ -1,107 +1,65 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
.completed {
text-decoration: line-through;
color: gray;
}

body {
background-color: #f4f4f4;
padding: 40px;
.todo-icon {
cursor: pointer;
margin-left: 8px;
font-size: 1.2rem;
padding: 8px;
color: inherit;
}

.todo-container {
max-width: 500px;
margin: 0 auto;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
.completed .fa-check {
color: green;
}

.todo-icon:hover {
opacity: 0.7;
}

h1 {
.todo-container {
max-width: 400px;
margin: 50px auto;
text-align: center;
margin-bottom: 20px;
}

.todo-input {
display: flex;
gap: 10px;
margin-bottom: 20px;
.todo-container form > div {
margin-bottom: 15px;
}

.todo-input input {
flex: 1;
#todoInput {
width: 100%;
padding: 10px;
font-size: 16px;
border-radius: 6px;
border: 1px solid #ccc;
font-size: 1rem;
}

.todo-input button {
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 6px;
button {
border-radius: 5px;
padding: 12px 20px;
font-size: 1rem;
cursor: pointer;
min-height: 44px;
}

.todo-input button:hover {
background-color: #45a049;
}

.todo-list {
list-style-type: none;
padding-left: 0;
button:hover {
opacity: 0.9;
}

.todo-item {
.list-group-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 10px;
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 6px;
background-color: #fff;
}

.description {
flex: 1;
margin-right: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.actions {
display: flex;
gap: 10px;
}

.actions button {
background: none;
border: none;
cursor: pointer;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 10px 15px;
margin-bottom: 8px;
}

.complete-btn i {
color: green;
}

.delete-btn i {
color: red;
}

.todo-item.completed .description {
text-decoration: line-through;
color: gray;
}
.badge {
display: flex;
gap: 8px;
padding: 6px 10px;
background-color: #f8f9fa;
color: #000;
border-radius: 50px;
}