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
97 changes: 60 additions & 37 deletions Sprint-3/todo-list/index.html
Original file line number Diff line number Diff line change
@@ -1,40 +1,63 @@
<!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>
<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" />
<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..."
aria-label="Enter a new task"
/>

<input
type="date"
id="deadline-input"
aria-label="Set a deadline"
/>

<button id="add-task-btn" type="button">Add</button>
</div>

<div class="todo-actions">
<button id="delete-completed-btn" type="button">
Delete Completed
</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>
</div>
</li>
</template>

</div>
</body>
</html>
<ul id="todo-list" class="todo-list"></ul>

<!--
Template used to create each todo list item in JavaScript.
Add class "completed" to <li> when the task is complete.
-->
<template id="todo-item-template">
<li class="todo-item">
<div class="todo-content">
<button class="complete-btn" type="button" aria-label="Complete task">
</button>

<div class="todo-text-group">
<span class="description">Task description</span>
<span class="deadline"></span>
</div>
</div>

<button class="delete-btn" type="button" aria-label="Delete task">
🗑
</button>
</li>
</template>
</div>
</body>
</html>
116 changes: 76 additions & 40 deletions Sprint-3/todo-list/script.mjs
Original file line number Diff line number Diff line change
@@ -1,42 +1,65 @@
// Store everything imported from './todos.mjs' module as properties of an object named Todos
// Import all exported functions from todos.mjs
import * as Todos from "./todos.mjs";

// To store the todo tasks
// Store todo tasks here
const todos = [];

// Set up tasks to be performed once on page load
// Cache DOM elements so we do not query the DOM repeatedly
const todoListEl = document.getElementById("todo-list");
const newTaskInputEl = document.getElementById("new-task-input");
const deadlineInputEl = document.getElementById("deadline-input");
const addTaskButtonEl = document.getElementById("add-task-btn");
const deleteCompletedButtonEl = document.getElementById("delete-completed-btn");

// Template for each todo list item
const todoListItemTemplate =
document.getElementById("todo-item-template").content.firstElementChild;

// Set up the app when the page loads
window.addEventListener("load", () => {
document.getElementById("add-task-btn").addEventListener("click", addNewTodo);
addTaskButtonEl.addEventListener("click", addNewTodo);
deleteCompletedButtonEl.addEventListener("click", deleteCompletedTodos);

// Populate sample data
Todos.addTask(todos, "Wash the dishes", false);
Todos.addTask(todos, "Do the shopping", true);
// Hardcoded sample tasks shown on page load
Todos.addTask(todos, "Wash the dishes", false, "");
Todos.addTask(todos, "Do the shopping", true, "2026-03-24");
Todos.addTask(todos, "Prepare for Saturday class", false, "2026-03-26");

render();
populateTodoList();
});


// A callback that reads the task description from an input field and
// append a new task to the todo list.
/**
* Reads input values and adds a new todo to the list.
*/
function addNewTodo() {
const taskInput = document.getElementById("new-task-input");
const task = taskInput.value.trim();
if (task) {
Todos.addTask(todos, task, false);
render();
const task = newTaskInputEl.value.trim();
const deadline = deadlineInputEl.value;

// Do not add empty tasks
if (!task) {
return;
}

taskInput.value = "";
Todos.addTask(todos, task, false, deadline);
populateTodoList();

// Clear inputs after adding
newTaskInputEl.value = "";
deadlineInputEl.value = "";
}

// Note:
// - Store the reference to the <ul> element with id "todo-list" here
// to avoid querying the DOM repeatedly inside render().
// - This variable is declared here to be close to the only function that uses it.
const todoListEl = document.getElementById("todo-list");
/**
* Deletes all completed todos.
*/
function deleteCompletedTodos() {
Todos.deleteCompletedTasks(todos);
populateTodoList();
}

// Render the whole todo list
function render() {
/**
* Clears and rebuilds the todo list from the hardcoded/current todos array.
*/
function populateTodoList() {
todoListEl.innerHTML = "";

todos.forEach((todo, index) => {
Expand All @@ -45,32 +68,45 @@ function render() {
});
}

/**
* Creates one <li> element for a given todo.
*/
function createListItem(todo, index) {
const li = todoListItemTemplate.cloneNode(true);

// Note:
// - First child of #todo-item-template is a <li> element.
// We will create each ToDo list item as a clone of this node.
// - This variable is declared here to be close to the only function that uses it.
const todoListItemTemplate =
document.getElementById("todo-item-template").content.firstElementChild;
const descriptionEl = li.querySelector(".description");
const deadlineEl = li.querySelector(".deadline");
const completeButtonEl = li.querySelector(".complete-btn");
const deleteButtonEl = li.querySelector(".delete-btn");

// Create a <li> element for the given todo task
function createListItem(todo, index) {
const li = todoListItemTemplate.cloneNode(true); // true => Do a deep copy of the node
descriptionEl.textContent = todo.task;

li.querySelector(".description").textContent = todo.task;
// Show deadline if one exists
if (todo.deadline) {
deadlineEl.textContent = `Deadline: ${todo.deadline}`;
} else {
deadlineEl.textContent = "";
}

// Show completed state
if (todo.completed) {
li.classList.add("completed");
completeButtonEl.textContent = "✅";
} else {
completeButtonEl.textContent = "☑";
}

li.querySelector('.complete-btn').addEventListener("click", () => {
// Toggle task completion
completeButtonEl.addEventListener("click", () => {
Todos.toggleCompletedOnTask(todos, index);
render();
populateTodoList();
});

li.querySelector('.delete-btn').addEventListener("click", () => {

// Delete individual task
deleteButtonEl.addEventListener("click", () => {
Todos.deleteTask(todos, index);
render();
populateTodoList();
});

return li;
}
}
Loading
Loading