diff --git a/Domains/Frontend/MiniProjects/TaskTracker/README.md b/Domains/Frontend/MiniProjects/TaskTracker/README.md new file mode 100644 index 00000000..16796473 --- /dev/null +++ b/Domains/Frontend/MiniProjects/TaskTracker/README.md @@ -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 +``` + +--- \ No newline at end of file diff --git a/Domains/Frontend/MiniProjects/TaskTracker/index.html b/Domains/Frontend/MiniProjects/TaskTracker/index.html new file mode 100644 index 00000000..6fca2865 --- /dev/null +++ b/Domains/Frontend/MiniProjects/TaskTracker/index.html @@ -0,0 +1,57 @@ + + + + + + Task Tracker with Deadlines + + + + + + + + + + + + + + + +
+ +
+

πŸ“‹ Task Tracker

+
+ + +
+
+ + + +
+
+ + +
+
+ Progress + 0/0 tasks done +
+
+
+
+
+ + +
+ +
+
+ + + + + diff --git a/Domains/Frontend/MiniProjects/TaskTracker/script.js b/Domains/Frontend/MiniProjects/TaskTracker/script.js new file mode 100644 index 00000000..e52e9c6e --- /dev/null +++ b/Domains/Frontend/MiniProjects/TaskTracker/script.js @@ -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 = `

No tasks yet. Add one above!

`; + } 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 = ` +
+

${task.text}

+

+ Deadline: ${task.deadline} ${isOverdue ? '(Overdue!)' : ''} +

+
+
+ + + +
+ `; + 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(); +}); diff --git a/Domains/Frontend/MiniProjects/TaskTracker/style.css b/Domains/Frontend/MiniProjects/TaskTracker/style.css new file mode 100644 index 00000000..e1512dd5 --- /dev/null +++ b/Domains/Frontend/MiniProjects/TaskTracker/style.css @@ -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; +}