TL;DR Developers can create a todo list application with features such as creating new tasks, editing existing tasks, deleting completed or irrelevant tasks, filtering tasks by category, and sorting tasks by priority, date, and category using HTML5, CSS3, JavaScript for the frontend and Node.js with Express to create API endpoints for interacting with MongoDB.
Building a Todo List Application to Manage Tasks
As developers, we've all been there – struggling to stay on top of our tasks and deadlines. A well-organized task management system can be the difference between a productive day and a chaotic one. In this article, we'll embark on a journey to build a todo list application that will revolutionize the way you manage your tasks.
What We're Building
Our todo list application will have the following features:
- Create new tasks with due dates and reminders
- Edit existing tasks
- Delete completed or irrelevant tasks
- Filter tasks by category (e.g., work, personal)
- Sort tasks by priority, date, and category
Frontend Development
We'll start with the frontend, using HTML5, CSS3, and JavaScript to create a user-friendly interface. Our application will have the following pages:
- Home Page: Displays all available categories (work, personal, etc.)
- Task List Page: Shows all tasks for the selected category
- New Task Form: Allows users to create new tasks with due dates and reminders
Home Page
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo List App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Categories list -->
<ul id="categories-list">
<li><a href="#" data-category="work">Work</a></li>
<li><a href="#" data-category="personal">Personal</a></li>
</ul>
<script src="scripts.js"></script>
</body>
</html>
Task List Page
<!-- task-list.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo List App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Task list -->
<ul id="task-list">
{% for task in tasks %}
<li>
<h2>{{ task.title }}</h2>
<p>{{ task.description }}</p>
<p>Due Date: {{ task.due_date }}</p>
<button class="delete-task">Delete</button>
</li>
{% endfor %}
</ul>
<script src="scripts.js"></script>
</body>
</html>
New Task Form
<!-- new-task.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo List App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- New task form -->
<form id="new-task-form">
<input type="text" id="task-title" placeholder="Task Title">
<input type="date" id="due-date" placeholder="Due Date">
<button class="create-task">Create Task</button>
</form>
<script src="scripts.js"></script>
</body>
</html>
Backend Development
For the backend, we'll use Node.js with Express to create API endpoints for creating, reading, updating, and deleting tasks. We'll also use MongoDB as our database to store task data.
Task Model
// models/task.js
const mongoose = require('mongoose');
const taskSchema = new mongoose.Schema({
title: String,
description: String,
due_date: Date,
category: String
});
module.exports = mongoose.model('Task', taskSchema);
API Endpoints
// routes/task.js
const express = require('express');
const Task = require('../models/task');
const router = express.Router();
router.get('/tasks', async (req, res) => {
const tasks = await Task.find().exec();
res.json(tasks);
});
router.post('/tasks', async (req, res) => {
const task = new Task(req.body);
await task.save();
res.json(task);
});
router.put('/tasks/:id', async (req, res) => {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, {new: true});
res.json(task);
});
router.delete('/tasks/:id', async (req, res) => {
await Task.findByIdAndRemove(req.params.id);
res.status(204).send();
});
module.exports = router;
Putting it all Together
With our frontend and backend components in place, we can now combine them to create a fully functional todo list application.
Frontend Code
// scripts.js
document.addEventListener('DOMContentLoaded', () => {
// Initialize task list page
const taskListPage = document.getElementById('task-list');
fetch('/tasks')
.then(response => response.json())
.then(tasks => {
tasks.forEach(task => {
const taskElement = document.createElement('li');
taskElement.innerHTML = `
<h2>${task.title}</h2>
<p>${task.description}</p>
<p>Due Date: ${task.due_date.toISOString()}</p>
<button class="delete-task">Delete</button>
`;
taskListPage.appendChild(taskElement);
});
});
// Handle new task form submission
const newTaskForm = document.getElementById('new-task-form');
newTaskForm.addEventListener('submit', async (event) => {
event.preventDefault();
const taskTitle = document.getElementById('task-title').value;
const dueDate = document.getElementById('due-date').value;
const category = 'work'; // Replace with actual category
const response = await fetch('/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: taskTitle, description: '', due_date: new Date(dueDate), category })
});
const task = await response.json();
console.log(task);
});
// Handle delete task button click
document.querySelectorAll('.delete-task').forEach((button) => {
button.addEventListener('click', async (event) => {
event.preventDefault();
const taskId = event.target.parentNode.dataset.id;
await fetch(`/tasks/${taskId}`, { method: 'DELETE' });
window.location.reload();
});
});
});
Conclusion
Congratulations! You've just built a fully functional todo list application from scratch. This application allows users to create new tasks, edit existing tasks, delete completed or irrelevant tasks, filter tasks by category, and sort tasks by priority, date, and category.
This is just the beginning of your journey as a full-stack developer. Practice building more complex applications, experimenting with different technologies, and exploring new features to enhance user experience.
Key Use Case
Workflow:
- User creates a new task: The user fills out the new task form on the frontend, selecting the category (e.g., work, personal) and entering the due date.
- Frontend sends request to backend: When the user submits the form, the frontend JavaScript code sends a POST request to the
/tasksendpoint with the task data in JSON format. - Backend creates new task document: The Node.js Express server receives the request and uses Mongoose to create a new Task document in the MongoDB database.
- Frontend retrieves updated task list: After creating the new task, the frontend JavaScript code sends a GET request to the
/tasksendpoint to retrieve the updated list of tasks. - User views updated task list: The frontend updates the task list page with the new task and displays it to the user.
Use case:
- A user wants to create a new task for their work category with a due date of tomorrow. They fill out the new task form on the frontend, select "work" as the category, and enter the due date.
- The frontend JavaScript code sends a POST request to the
/tasksendpoint with the task data in JSON format. - The Node.js Express server receives the request and creates a new Task document in the MongoDB database with the specified details.
- The frontend retrieves the updated list of tasks from the backend and updates the task list page, displaying the new task to the user.
Finally
As we continue to build our todo list application, let's focus on implementing the backend logic for creating, reading, updating, and deleting tasks. We'll use Node.js with Express to create API endpoints for interacting with our MongoDB database. The task model will be defined using Mongoose, allowing us to easily interact with our MongoDB collection.
// models/task.js
const mongoose = require('mongoose');
const taskSchema = new mongoose.Schema({
title: String,
description: String,
due_date: Date,
category: String
});
module.exports = mongoose.model('Task', taskSchema);
With the task model in place, we can now define our API endpoints using Express. We'll create routes for creating new tasks, retrieving existing tasks, updating existing tasks, and deleting tasks.
// routes/task.js
const express = require('express');
const Task = require('../models/task');
const router = express.Router();
router.get('/tasks', async (req, res) => {
const tasks = await Task.find().exec();
res.json(tasks);
});
router.post('/tasks', async (req, res) => {
const task = new Task(req.body);
await task.save();
res.json(task);
});
router.put('/tasks/:id', async (req, res) => {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, {new: true});
res.json(task);
});
router.delete('/tasks/:id', async (req, res) => {
await Task.findByIdAndRemove(req.params.id);
res.status(204).send();
});
module.exports = router;
By combining the frontend and backend components, we can create a fully functional todo list application that allows users to manage their tasks efficiently. With this implementation, we've covered the key features of creating new tasks, editing existing tasks, deleting completed or irrelevant tasks, filtering tasks by category, and sorting tasks by priority, date, and category.
Recommended Books
- "The Pragmatic Programmer: From Journeyman to Master" by Andrew Hunt and David Thomas - A classic book for programmers that provides practical advice on improving coding skills, communication, and collaboration.
- "Clean Code: A Handbook of Agile Software Craftsmanship" by Robert C. Martin - A comprehensive guide to writing clean, maintainable code with principles and techniques for improving code quality.
- "Introduction to Algorithms" by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein - A thorough textbook on algorithms that covers data structures, sorting, searching, and graph algorithms.
