TaskMaster Pro – Daily Task Manager
https://cdn.tailwindcss.com
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.task-item {
animation: fadeIn 0.3s ease-out;
}
.priority-high {
border-left: 4px solid #ef4444;
}
.priority-medium {
border-left: 4px solid #f59e0b;
}
.priority-low {
border-left: 4px solid #10b981;
}
.completed-task {
background-color: #f3f4f6;
text-decoration: line-through;
color: #9ca3af;
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
.table-row-high {
background-color: #fee2e2;
}
.table-row-medium {
background-color: #fef3c7;
}
.table-row-low {
background-color: #d1fae5;
}
.table-row-completed {
background-color: #f3f4f6;
}
.view-toggle {
transition: all 0.3s ease;
}
.view-toggle.active {
background-color: #6366f1;
color: white;
}
.day-tab {
transition: all 0.3s ease;
}
.day-tab.active {
background-color: #6366f1;
color: white;
}
.time-input {
width: 70px;
}
.day-column {
min-width: 300px;
}
TaskMaster Pro
Your daily productivity companion with time management
Add New Task with Time
Task Title
Description (Optional)
Due Date
Start Time
End Time
Priority
Low
Medium
High
Category
Work
Personal
Health
Education
Other
Add Task
All Tasks
Today
Tomorrow
This Week
Overdue
Daily Task Management
All Priorities
High
Medium
Low
All Categories
Work
Personal
Health
Education
Other
All Status
Completed
Pending
Cards
Table
Day View
|
Status
|
Task
|
Description
|
Time
|
Priority
|
Category
|
Due Date
|
Actions
|
No tasks yet
Add your first task to get started!
No tasks scheduled
Add tasks with dates to see them in day view
document.addEventListener(‘DOMContentLoaded’, function() {
// Initialize tasks array from localStorage or empty array
let tasks = JSON.parse(localStorage.getItem(‘tasks’)) || [];
// DOM elements
const taskForm = document.getElementById(‘task-form’);
const cardView = document.getElementById(‘card-view’);
const tableView = document.getElementById(‘table-view’);
const dayView = document.getElementById(‘day-view’);
const tableBody = document.getElementById(‘table-body’);
const dayColumnsContainer = document.getElementById(‘day-columns-container’);
const emptyState = document.getElementById(’empty-state’);
const tableEmptyState = document.getElementById(‘table-empty-state’);
const dayEmptyState = document.getElementById(‘day-empty-state’);
const filterPriority = document.getElementById(‘filter-priority’);
const filterCategory = document.getElementById(‘filter-category’);
const filterStatus = document.getElementById(‘filter-status’);
const totalTasksEl = document.getElementById(‘total-tasks’);
const completedTasksEl = document.getElementById(‘completed-tasks’);
const pendingTasksEl = document.getElementById(‘pending-tasks’);
const todayTasksEl = document.getElementById(‘today-tasks’);
const cardViewBtn = document.getElementById(‘card-view-btn’);
const tableViewBtn = document.getElementById(‘table-view-btn’);
const dayViewBtn = document.getElementById(‘day-view-btn’);
const dayTabs = document.querySelectorAll(‘.day-tab’);
// Set today’s date as default in the date picker
document.getElementById(‘task-due-date’).valueAsDate = new Date();
// Update stats
function updateStats() {
const total = tasks.length;
const completed = tasks.filter(task => task.completed).length;
const pending = total – completed;
// Count today’s tasks
const today = new Date().toISOString().split(‘T’)[0];
const todayTasks = tasks.filter(task => task.dueDate === today).length;
totalTasksEl.textContent = total;
completedTasksEl.textContent = completed;
pendingTasksEl.textContent = pending;
todayTasksEl.textContent = todayTasks;
}
// Save tasks to localStorage
function saveTasks() {
localStorage.setItem(‘tasks’, JSON.stringify(tasks));
updateStats();
}
// Toggle between card, table and day views
function toggleView(view) {
if (view === ‘card’) {
cardView.classList.remove(‘hidden’);
tableView.classList.add(‘hidden’);
dayView.classList.add(‘hidden’);
cardViewBtn.classList.add(‘active’);
tableViewBtn.classList.remove(‘active’);
dayViewBtn.classList.remove(‘active’);
} else if (view === ‘table’) {
cardView.classList.add(‘hidden’);
tableView.classList.remove(‘hidden’);
dayView.classList.add(‘hidden’);
cardViewBtn.classList.remove(‘active’);
tableViewBtn.classList.add(‘active’);
dayViewBtn.classList.remove(‘active’);
renderTableView();
} else if (view === ‘day’) {
cardView.classList.add(‘hidden’);
tableView.classList.add(‘hidden’);
dayView.classList.remove(‘hidden’);
cardViewBtn.classList.remove(‘active’);
tableViewBtn.classList.remove(‘active’);
dayViewBtn.classList.add(‘active’);
renderDayView();
}
}
// Event listeners for view toggle buttons
cardViewBtn.addEventListener(‘click’, () => toggleView(‘card’));
tableViewBtn.addEventListener(‘click’, () => toggleView(‘table’));
dayViewBtn.addEventListener(‘click’, () => toggleView(‘day’));
// Event listeners for day tabs
dayTabs.forEach(tab => {
tab.addEventListener(‘click’, function() {
dayTabs.forEach(t => t.classList.remove(‘active’));
this.classList.add(‘active’);
renderTasks();
});
});
// Get current day filter
function getCurrentDayFilter() {
const activeTab = document.querySelector(‘.day-tab.active’);
return activeTab ? activeTab.getAttribute(‘data-day’) : ‘all’;
}
// Filter tasks by day
function filterTasksByDay(tasks, dayFilter) {
const today = new Date().toISOString().split(‘T’)[0];
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const tomorrowStr = tomorrow.toISOString().split(‘T’)[0];
const nextWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);
switch(dayFilter) {
case ‘today’:
return tasks.filter(task => task.dueDate === today);
case ‘tomorrow’:
return tasks.filter(task => task.dueDate === tomorrowStr);
case ‘week’:
return tasks.filter(task => {
const taskDate = new Date(task.dueDate);
return taskDate = new Date(today);
});
case ‘overdue’:
return tasks.filter(task => {
if (!task.dueDate) return false;
return new Date(task.dueDate) task.priority === priorityFilter);
}
// Apply category filter
if (categoryFilter !== ‘all’) {
filteredTasks = filteredTasks.filter(task => task.category === categoryFilter);
}
// Apply status filter
if (statusFilter !== ‘all’) {
const isCompleted = statusFilter === ‘completed’;
filteredTasks = filteredTasks.filter(task => task.completed === isCompleted);
}
// Clear card view
cardView.innerHTML = ”;
// Show empty state if no tasks
if (filteredTasks.length === 0) {
cardView.appendChild(emptyState);
emptyState.style.display = ‘block’;
tableEmptyState.classList.remove(‘hidden’);
tableBody.innerHTML = ”;
} else {
emptyState.style.display = ‘none’;
tableEmptyState.classList.add(‘hidden’);
// Add each task to the card view
filteredTasks.forEach((task, index) => {
const taskItem = createTaskElement(task, index);
cardView.appendChild(taskItem);
});
// If table view is active, render it
if (!tableView.classList.contains(‘hidden’)) {
renderTableView();
}
// If day view is active, render it
if (!dayView.classList.contains(‘hidden’)) {
renderDayView();
}
}
}
// Render table view
function renderTableView() {
const priorityFilter = filterPriority.value;
const categoryFilter = filterCategory.value;
const statusFilter = filterStatus.value;
const dayFilter = getCurrentDayFilter();
let filteredTasks = tasks;
// Apply day filter
filteredTasks = filterTasksByDay(filteredTasks, dayFilter);
// Apply priority filter
if (priorityFilter !== ‘all’) {
filteredTasks = filteredTasks.filter(task => task.priority === priorityFilter);
}
// Apply category filter
if (categoryFilter !== ‘all’) {
filteredTasks = filteredTasks.filter(task => task.category === categoryFilter);
}
// Apply status filter
if (statusFilter !== ‘all’) {
const isCompleted = statusFilter === ‘completed’;
filteredTasks = filteredTasks.filter(task => task.completed === isCompleted);
}
// Clear table body
tableBody.innerHTML = ”;
// Show empty state if no tasks
if (filteredTasks.length === 0) {
tableEmptyState.classList.remove(‘hidden’);
} else {
tableEmptyState.classList.add(‘hidden’);
// Add each task to the table
filteredTasks.forEach((task, index) => {
const tableRow = createTableRow(task, index);
tableBody.appendChild(tableRow);
});
}
}
// Render day view
function renderDayView() {
// Clear existing columns
dayColumnsContainer.innerHTML = ”;
// Get filtered tasks
const priorityFilter = filterPriority.value;
const categoryFilter = filterCategory.value;
const statusFilter = filterStatus.value;
const dayFilter = getCurrentDayFilter();
let filteredTasks = tasks;
// Apply day filter
filteredTasks = filterTasksByDay(filteredTasks, dayFilter);
// Apply priority filter
if (priorityFilter !== ‘all’) {
filteredTasks = filteredTasks.filter(task => task.priority === priorityFilter);
}
// Apply category filter
if (categoryFilter !== ‘all’) {
filteredTasks = filteredTasks.filter(task => task.category === categoryFilter);
}
// Apply status filter
if (statusFilter !== ‘all’) {
const isCompleted = statusFilter === ‘completed’;
filteredTasks = filteredTasks.filter(task => task.completed === isCompleted);
}
// Group tasks by date
const tasksByDate = {};
filteredTasks.forEach(task => {
const date = task.dueDate || ‘No date’;
if (!tasksByDate[date]) {
tasksByDate[date] = [];
}
tasksByDate[date].push(task);
});
// Show empty state if no tasks
if (Object.keys(tasksByDate).length === 0) {
dayEmptyState.classList.remove(‘hidden’);
return;
} else {
dayEmptyState.classList.add(‘hidden’);
}
// Create columns for each date
Object.keys(tasksByDate).forEach(date => {
const dateColumn = document.createElement(‘div’);
dateColumn.className = ‘day-column bg-gray-50 rounded-lg p-4’;
// Format date header
let dateHeader;
if (date === ‘No date’) {
dateHeader = ‘No Date Set’;
} else {
const dateObj = new Date(date);
const options = { weekday: ‘long’, year: ‘numeric’, month: ‘long’, day: ‘numeric’ };
dateHeader = dateObj.toLocaleDateString(undefined, options);
// Highlight today
const today = new Date().toISOString().split(‘T’)[0];
if (date === today) {
dateHeader += ‘ (Today)’;
}
}
dateColumn.innerHTML = `
${dateHeader}
`;
dayColumnsContainer.appendChild(dateColumn);
// Add tasks to this date column
const tasksContainer = dateColumn.querySelector(`#tasks-${date.replace(/\s+/g, ‘-‘)}`);
tasksByDate[date].forEach((task, index) => {
const taskIndex = tasks.findIndex(t => t === task);
if (taskIndex !== -1) {
const taskItem = createDayViewTaskElement(task, taskIndex);
tasksContainer.appendChild(taskItem);
}
});
});
}
// Create task element for card view
function createTaskElement(task, index) {
const taskItem = document.createElement(‘div’);
taskItem.className = `task-item p-4 hover:bg-gray-50 transition-colors ${task.completed ? ‘completed-task’ : ”} priority-${task.priority}`;
// Format due date
const dueDate = task.dueDate ? new Date(task.dueDate).toLocaleDateString() : ‘No due date’;
// Format time range
let timeRange = ”;
if (task.startTime && task.endTime) {
timeRange = `${task.startTime} – ${task.endTime}`;
} else if (task.startTime) {
timeRange = `Starts at ${task.startTime}`;
} else if (task.endTime) {
timeRange = `Ends at ${task.endTime}`;
}
// Priority badge color
let priorityColor = ‘bg-gray-100 text-gray-800’;
if (task.priority === ‘high’) priorityColor = ‘bg-red-100 text-red-800’;
else if (task.priority === ‘medium’) priorityColor = ‘bg-amber-100 text-amber-800’;
else if (task.priority === ‘low’) priorityColor = ‘bg-green-100 text-green-800’;
// Category badge color
let categoryColor = ‘bg-gray-100 text-gray-800’;
if (task.category === ‘work’) categoryColor = ‘bg-blue-100 text-blue-800’;
else if (task.category === ‘personal’) categoryColor = ‘bg-purple-100 text-purple-800’;
else if (task.category === ‘health’) categoryColor = ‘bg-green-100 text-green-800’;
else if (task.category === ‘education’) categoryColor = ‘bg-yellow-100 text-yellow-800’;
taskItem.innerHTML = `
${task.title}
${task.description ? `
${task.description}
` : ”}
${task.priority}
${task.category}
${timeRange ? `${timeRange}` : ”}
${dueDate}
`;
return taskItem;
}
// Create table row for table view
function createTableRow(task, index) {
const row = document.createElement(‘tr’);
// Set row background based on priority and completion status
let rowClass = ”;
if (task.completed) {
rowClass = ‘table-row-completed’;
} else {
if (task.priority === ‘high’) rowClass = ‘table-row-high’;
else if (task.priority === ‘medium’) rowClass = ‘table-row-medium’;
else if (task.priority === ‘low’) rowClass = ‘table-row-low’;
}
row.className = rowClass;
// Format due date
const dueDate = task.dueDate ? new Date(task.dueDate).toLocaleDateString() : ‘Not set’;
// Format time range
let timeRange = ”;
if (task.startTime && task.endTime) {
timeRange = `${task.startTime} – ${task.endTime}`;
} else if (task.startTime) {
timeRange = `Starts: ${task.startTime}`;
} else if (task.endTime) {
timeRange = `Ends: ${task.endTime}`;
}
// Priority badge color
let priorityColor = ‘bg-gray-100 text-gray-800’;
if (task.priority === ‘high’) priorityColor = ‘bg-red-100 text-red-800’;
else if (task.priority === ‘medium’) priorityColor = ‘bg-amber-100 text-amber-800’;
else if (task.priority === ‘low’) priorityColor = ‘bg-green-100 text-green-800’;
// Category badge color
let categoryColor = ‘bg-gray-100 text-gray-800’;
if (task.category === ‘work’) categoryColor = ‘bg-blue-100 text-blue-800’;
else if (task.category === ‘personal’) categoryColor = ‘bg-purple-100 text-purple-800’;
else if (task.category === ‘health’) categoryColor = ‘bg-green-100 text-green-800’;
else if (task.category === ‘education’) categoryColor = ‘bg-yellow-100 text-yellow-800’;
row.innerHTML = `
${task.completed ? ‘Completed’ : ‘Pending’}
|
${task.title}
|
${task.description || ‘No description’}
|
${timeRange || ‘No time set’}
|
${task.priority}
|
${task.category}
|
${dueDate}
|
|
`;
return row;
}
// Create task element for day view
function createDayViewTaskElement(task, index) {
const taskItem = document.createElement(‘div’);
taskItem.className = `task-item bg-white p-3 rounded-lg shadow-sm border border-gray-200 hover:shadow-md transition-shadow ${task.completed ? ‘completed-task’ : ”}`;
// Format time range
let timeRange = ”;
if (task.startTime && task.endTime) {
timeRange = `${task.startTime} – ${task.endTime}`;
} else if (task.startTime) {
timeRange = `Starts at ${task.startTime}`;
} else if (task.endTime) {
timeRange = `Ends at ${task.endTime}`;
}
// Priority indicator
let priorityIndicator = ”;
if (task.priority === ‘high’) priorityIndicator = ‘
‘;
else if (task.priority === ‘medium’) priorityIndicator = ‘
‘;
else if (task.priority === ‘low’) priorityIndicator = ‘
‘;
taskItem.innerHTML = `
${task.title}
${priorityIndicator}
${timeRange ? `${timeRange}` : ”}
`;
return taskItem;
}
// Add new task
taskForm.addEventListener(‘submit’, function(e) {
e.preventDefault();
const title = document.getElementById(‘task-title’).value;
const description = document.getElementById(‘task-description’).value;
const dueDate = document.getElementById(‘task-due-date’).value;
const startTime = document.getElementById(‘task-start-time’).value;
const endTime = document.getElementById(‘task-end-time’).value;
const priority = document.getElementById(‘task-priority’).value;
const category = document.getElementById(‘task-category’).value;
const newTask = {
title,
description,
dueDate,
startTime,
endTime,
priority,
category,
completed: false,
createdAt: new Date().toISOString()
};
tasks.push(newTask);
saveTasks();
renderTasks();
// Reset form
taskForm.reset();
document.getElementById(‘task-priority’).value = ‘medium’;
document.getElementById(‘task-category’).value = ‘work’;
document.getElementById(‘task-due-date’).valueAsDate = new Date();
});
// Complete task
function handleCompleteTask(index) {
tasks[index].completed = !tasks[index].completed;
saveTasks();
renderTasks();
}
// Delete task
function handleDeleteTask(index) {
if (confirm(‘Are you sure you want to delete this task?’)) {
tasks.splice(index, 1);
saveTasks();
renderTasks();
}
}
// Edit task
function handleEditTask(index) {
const task = tasks[index];
// Fill the form with task data
document.getElementById(‘task-title’).value = task.title;
document.getElementById(‘task-description’).value = task.description || ”;
document.getElementById(‘task-due-date’).value = task.dueDate || ”;
document.getElementById(‘task-start-time’).value = task.startTime || ”;
document.getElementById(‘task-end-time’).value = task.endTime || ”;
document.getElementById(‘task-priority’).value = task.priority;
document.getElementById(‘task-category’).value = task.category;
// Remove the task from the array
tasks.splice(index, 1);
saveTasks();
renderTasks();
// Scroll to the form
document.getElementById(‘task-form’).scrollIntoView({ behavior: ‘smooth’ });
}
// Event delegation for card view
cardView.addEventListener(‘click’, function(e) {
if (e.target.closest(‘.complete-btn’)) {
const index = e.target.closest(‘.complete-btn’).getAttribute(‘data-index’);
handleCompleteTask(index);
}
if (e.target.closest(‘.delete-btn’)) {
const index = e.target.closest(‘.delete-btn’).getAttribute(‘data-index’);
handleDeleteTask(index);
}
if (e.target.closest(‘.edit-btn’)) {
const index = e.target.closest(‘.edit-btn’).getAttribute(‘data-index’);
handleEditTask(index);
}
});
// Event delegation for table view
tableBody.addEventListener(‘click’, function(e) {
if (e.target.closest(‘.complete-btn’)) {
const index = e.target.closest(‘.complete-btn’).getAttribute(‘data-index’);
handleCompleteTask(index);
}
if (e.target.closest(‘.delete-btn’)) {
const index = e.target.closest(‘.delete-btn’).getAttribute(‘data-index’);
handleDeleteTask(index);
}
if (e.target.closest(‘.edit-btn’)) {
const index = e.target.closest(‘.edit-btn’).getAttribute(‘data-index’);
handleEditTask(index);
}
});
// Event delegation for day view
dayColumnsContainer.addEventListener(‘click’, function(e) {
if (e.target.closest(‘.complete-btn’)) {
const index = e.target.closest(‘.complete-btn’).getAttribute(‘data-index’);
handleCompleteTask(index);
}
if (e.target.closest(‘.delete-btn’)) {
const index = e.target.closest(‘.delete-btn’).getAttribute(‘data-index’);
handleDeleteTask(index);
}
if (e.target.closest(‘.edit-btn’)) {
const index = e.target.closest(‘.edit-btn’).getAttribute(‘data-index’);
handleEditTask(index);
}
});
// Filter tasks
filterPriority.addEventListener(‘change’, renderTasks);
filterCategory.addEventListener(‘change’, renderTasks);
filterStatus.addEventListener(‘change’, renderTasks);
// Initial render
updateStats();
renderTasks();
});
Bình luận về bài viết này