Skip to content
Merged
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
67 changes: 67 additions & 0 deletions Domains/Frontend/MiniProjects/TaskTracker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# ✅ Task Tracker with Deadlines

**Contributor:** Tanmay-Kad
**Domain:** Frontend Development
**Difficulty:** Beginner
**Tech Stack:** HTML, CSS, JavaScript, Tailwind CSS

---

## 📝 Description

**Task Tracker with Deadlines** is a smart and interactive web app designed to help users manage tasks efficiently.
It allows you to **add tasks with specific deadlines**, automatically highlights **overdue tasks**, and displays your overall **progress visually**.
All your tasks are stored securely in the **browser’s LocalStorage**, ensuring that your data stays even after page reloads.

This project is perfect for beginners who want to learn **JavaScript DOM manipulation**, **state management**, and **responsive UI design** with Tailwind CSS.

---

## 🎯 Features

- ✅ Add new tasks with deadlines
- ✅ Edit existing tasks easily
- ✅ Delete unwanted tasks
- ✅ Mark tasks as complete/incomplete
- ✅ Sort tasks automatically by upcoming deadlines
- ✅ Highlight overdue tasks in red
- ✅ View completion progress with a live progress bar
- ✅ Data saved automatically using LocalStorage
- ✅ Fully responsive and mobile-friendly UI

---
## 🛠️ Tech Stack

- **HTML5** - Semantic markup
- **CSS3** - Modern styling with Flexbox
- **JavaScript (ES6+)** - DOM manipulation and logic
- **LocalStorage API** - Data persistence

---

## 🚀 How to Run

### Method 1: Open Directly
1. Download or clone this repository
2. Open `index.html` in your browser
3. Start adding and managing your tasks!

### Method 2: Run via Live Server (Recommended)
1. Open the project folder in **VS Code**
2. Install the **Live Server** extension (if not already installed)
3. Right-click `index.html` → Click **"Open with Live Server"**
4. App will open in your browser (usually at `http://localhost:5500`)

---

## 📁 Project Structure

```
TaskTracker/
├── index.html # Main HTML structure
├── style.css # Custom CSS styling
├── script.js # JavaScript logic and LocalStorage handling
└── README.md # Project documentation
```

---
57 changes: 57 additions & 0 deletions Domains/Frontend/MiniProjects/TaskTracker/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Tracker with Deadlines</title>

<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>

<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">

<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">

<!-- External CSS -->
<link rel="stylesheet" href="style.css">
</head>
<body class="text-gray-800">

<div class="container mx-auto p-4 max-w-2xl">
<!-- Header -->
<header class="text-center my-6">
<h1 class="text-4xl font-bold text-gray-700">📋 Task Tracker</h1>
</header>

<!-- Add Task Form -->
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
<form id="task-form" class="flex flex-col sm:flex-row gap-4">
<input type="text" id="task-input" class="flex-grow p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Add a new task..." required>
<input type="date" id="task-deadline" class="p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required>
<button type="submit" class="bg-blue-600 text-white font-semibold px-6 py-3 rounded-md hover:bg-blue-700 transition-colors">Add Task</button>
</form>
</div>

<!-- Progress Bar -->
<div class="bg-white rounded-lg shadow-md p-4 mb-6">
<div class="flex justify-between items-center mb-2">
<span class="font-semibold">Progress</span>
<span id="progress-text" class="text-sm text-gray-600">0/0 tasks done</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="progress-bar" class="bg-green-500 h-4 rounded-full progress-bar-fill" style="width: 0%"></div>
</div>
</div>

<!-- Task List -->
<main id="task-list" class="space-y-4">
<!-- Tasks will be rendered here -->
</main>
</div>

<!-- External JS -->
<script src="script.js"></script>
</body>
</html>
130 changes: 130 additions & 0 deletions Domains/Frontend/MiniProjects/TaskTracker/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
document.addEventListener('DOMContentLoaded', () => {
const taskForm = document.getElementById('task-form');
const taskInput = document.getElementById('task-input');
const taskDeadlineInput = document.getElementById('task-deadline');
const taskList = document.getElementById('task-list');
const progressText = document.getElementById('progress-text');
const progressBar = document.getElementById('progress-bar');

// Load tasks from LocalStorage
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];

// --- Main Render Function ---
const renderTasks = () => {
taskList.innerHTML = '';
tasks.sort((a, b) => new Date(a.deadline) - new Date(b.deadline)); // Sort by deadline

if (tasks.length === 0) {
taskList.innerHTML = `<p class="text-center text-gray-500">No tasks yet. Add one above!</p>`;
} else {
tasks.forEach(task => {
const taskItem = document.createElement('div');
const isCompleted = task.completed;
const today = new Date().toISOString().split('T')[0];
const isOverdue = !isCompleted && task.deadline < today;

let cardColorClass = 'bg-white';
if (isCompleted) {
cardColorClass = 'bg-green-100';
} else if (isOverdue) {
cardColorClass = 'bg-red-100';
}

taskItem.className = `task-item flex items-center p-4 rounded-lg shadow-sm ${cardColorClass} ${isCompleted ? 'completed' : ''}`;
taskItem.dataset.id = task.id;

taskItem.innerHTML = `
<div class="flex-grow">
<p class="font-semibold text-lg ${isCompleted ? 'text-gray-500' : 'text-gray-800'}">${task.text}</p>
<p class="text-sm ${isCompleted ? 'text-gray-400' : isOverdue ? 'text-red-600 font-semibold' : 'text-gray-500'}">
<i class="fa-regular fa-calendar"></i> Deadline: ${task.deadline} ${isOverdue ? '(Overdue!)' : ''}
</p>
</div>
<div class="flex items-center space-x-3">
<button class="toggle-btn text-2xl">${isCompleted ? '<i class="fa-solid fa-square-check text-green-600"></i>' : '<i class="fa-regular fa-square text-gray-400"></i>'}</button>
<button class="edit-btn text-blue-500 hover:text-blue-700"><i class="fas fa-edit"></i></button>
<button class="delete-btn text-red-500 hover:text-red-700"><i class="fas fa-trash"></i></button>
</div>
`;
taskList.appendChild(taskItem);
});
}
updateProgress();
};

// --- Update Progress Bar ---
const updateProgress = () => {
const completedTasks = tasks.filter(task => task.completed).length;
const totalTasks = tasks.length;

progressText.textContent = `${completedTasks}/${totalTasks} tasks done`;

if (totalTasks === 0) {
progressBar.style.width = '0%';
} else {
const percentage = (completedTasks / totalTasks) * 100;
progressBar.style.width = `${percentage}%`;
}
};

// --- Save tasks to LocalStorage ---
const saveTasks = () => {
localStorage.setItem('tasks', JSON.stringify(tasks));
};

// --- Event: Add a Task ---
taskForm.addEventListener('submit', (e) => {
e.preventDefault();
const taskText = taskInput.value.trim();
const taskDeadline = taskDeadlineInput.value;

if (taskText === '' || taskDeadline === '') return;

const newTask = {
id: Date.now(),
text: taskText,
deadline: taskDeadline,
completed: false
};

tasks.push(newTask);
saveTasks();
renderTasks();

taskInput.value = '';
taskDeadlineInput.value = '';
});

// --- Event: Click on a Task (Toggle, Edit, Delete) ---
taskList.addEventListener('click', (e) => {
const taskItem = e.target.closest('.task-item');
if (!taskItem) return;

const taskId = Number(taskItem.dataset.id);
const task = tasks.find(t => t.id === taskId);

// Toggle complete
if (e.target.closest('.toggle-btn')) {
task.completed = !task.completed;
}

// Delete task
if (e.target.closest('.delete-btn')) {
tasks = tasks.filter(t => t.id !== taskId);
}

// Edit task
if (e.target.closest('.edit-btn')) {
const newText = prompt('Edit your task:', task.text);
if (newText !== null && newText.trim() !== '') {
task.text = newText.trim();
}
}

saveTasks();
renderTasks();
});

// Initial render
renderTasks();
});
17 changes: 17 additions & 0 deletions Domains/Frontend/MiniProjects/TaskTracker/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
body {
font-family: 'Inter', sans-serif;
background-color: #f4f7f6;
}

.task-item {
transition: all 0.2s ease-in-out;
}

.task-item.completed {
text-decoration: line-through;
opacity: 0.6;
}

.progress-bar-fill {
transition: width 0.5s ease-in-out;
}
Loading