Demo Code for Task Manager App using HTML,CSS and Modern JavaScrip concepts
Demo Code for Task Manager App using HTML,CSS and Modern JavaScrip concepts
Problem Solving & Doubt Clearing : Electives III - Modern JavaScript From
The Beginning 2.0 (2024)
Demo Code for Task Manager App using HTML,CSS and Modern JavaScrip concepts
Time:30 mins
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modern Task Manager</title>
<style>
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--danger-color: #e74c3c;
--background-color: #f5f6fa;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', sans-serif;
background-color: var(--background-color);
line-height: 1.6;
}
.container {
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
.header {
text-align: center;
margin-bottom: 2rem;
}
.task-form {
background: white;
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 2rem;
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.btn {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: opacity 0.2s;
}
.btn:hover {
opacity: 0.9;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-danger {
background-color: var(--danger-color);
color: white;
}
.task-list {
display: grid;
gap: 1rem;
}
.task-item {
background: white;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
display: grid;
gap: 0.5rem;
opacity: 1;
transition: opacity 0.3s;
}
.task-item.completed {
opacity: 0.7;
}
.task-item h3 {
margin: 0;
color: var(--primary-color);
}
.task-actions {
display: flex;
gap: 0.5rem;
}
.loading {
text-align: center;
padding: 2rem;
}
.error {
color: var(--danger-color);
padding: 1rem;
background: rgba(231, 76, 60, 0.1);
border-radius: 4px;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<div class="container">
<header class="header">
<h1>Task Manager</h1>
</header>
<div id="errorContainer"></div>
<div id="taskList" class="task-list"></div>
</div>
<script type="module">
// ES Modules
import { TaskManager } from './modules/TaskManager.js';
import { StorageService } from './modules/StorageService.js';
import { UIManager } from './modules/UIManager.js';
import { ValidationService } from './modules/ValidationService.js';
this.init();
}
async init() {
try {
// Initialize observers
this.setupIntersectionObserver();
setupIntersectionObserver() {
const options = {
root: null,
threshold: 0.1
};
async loadTasks() {
const tasks = await this.taskManager.getAllTasks();
this.uiManager.renderTasks(tasks);
}
setupEventListeners() {
// Event delegation for task list
document.getElementById('taskList').addEventListener('click', async (e) => {
const taskId = e.target.closest('.task-item')?.dataset.id;
if (!taskId) return;
if (e.target.matches('.btn-complete')) {
await this.toggleTaskComplete(taskId);
} else if (e.target.matches('.btn-delete')) {
await this.deleteTask(taskId);
}
});
// Form submission
document.getElementById('taskForm').addEventListener('submit', async (e) => {
e.preventDefault();
await this.handleTaskSubmission(e);
});
}
async handleTaskSubmission(e) {
try {
const formData = new FormData(e.target);
const taskData = Object.fromEntries(formData.entries());
async toggleTaskComplete(taskId) {
try {
const updatedTask = await this.taskManager.toggleTaskComplete(taskId);
this.uiManager.updateTaskUI(updatedTask);
} catch (error) {
this.handleError(error);
}
}
async deleteTask(taskId) {
try {
await this.taskManager.deleteTask(taskId);
this.uiManager.removeTaskFromUI(taskId);
} catch (error) {
this.handleError(error);
}
}
handleError(error) {
console.error('Application Error:', error);
this.uiManager.showError(error.message);
}
}
// Initialize app
new App();
</script>
async getAllTasks() {
try {
return await this.storageService.getTasks();
} catch (error) {
throw new Error('Failed to fetch tasks');
}
}
await this.storageService.saveTask(task);
return task;
}
async toggleTaskComplete(taskId) {
const task = await this.storageService.getTask(taskId);
task.completed = !task.completed;
await this.storageService.updateTask(task);
return task;
}
async deleteTask(taskId) {
await this.storageService.deleteTask(taskId);
}
}
</script>
async getTasks() {
const tasks = localStorage.getItem(this.STORAGE_KEY);
return tasks ? JSON.parse(tasks) : [];
}
async getTask(taskId) {
const tasks = await this.getTasks();
return tasks.find(task => task.id === taskId);
}
async saveTask(task) {
const tasks = await this.getTasks();
tasks.push(task);
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(tasks));
}
async updateTask(updatedTask) {
const tasks = await this.getTasks();
const index = tasks.findIndex(task => task.id === updatedTask.id);
if (index !== -1) {
tasks[index] = updatedTask;
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(tasks));
}
}
async deleteTask(taskId) {
const tasks = await this.getTasks();
const filteredTasks = tasks.filter(task => task.id !== taskId);
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(filteredTasks));
}
}
</script>
renderTasks(tasks) {
this.taskList.innerHTML = tasks.map(task => this.createTaskHTML(task)).join('');
}
createTaskHTML(task) {
return `
<div class="task-item ${task.completed ? 'completed' : ''}" data-id="${task.id}">
<h3>${task.title}</h3>
<p>${task.description}</p>
<div class="task-meta">
<span class="priority ${task.priority}">${task.priority}</span>
<span class="date">${new Date(task.createdAt).toLocaleDateString()}</span>
</div>
<div class="task-actions">
<button class="btn btn-primary btn-complete">
${task.completed ? 'Undo' : 'Complete'}
</button>
<button class="btn btn-danger btn-delete">Delete</button>
</div>
</div>
`;
}
addTaskToList(task) {
this.taskList.insertAdjacentHTML('afterbegin', this.createTaskHTML(task));
}
updateTaskUI(task) {
const taskElement = this.taskList.querySelector(`[data-id="${task.id}"]`);
if (taskElement) {
taskElement.outerHTML = this.createTaskHTML(task);
}
}
removeTaskFromUI(taskId) {
const taskElement = this.taskList.querySelector(`[data-id="${taskId}"]`);
if (taskElement) {
taskElement.remove();
}
}
showError(message) {
this.errorContainer.innerHTML = `
<div class="error">
${message}
</div>
`;
setTimeout(() => {
this.errorContainer.innerHTML = '';
}, 3000);
}
}
</script>
return true;
}
}
</script>
</body>
</html>