deepseek-task-matrix / index.html
mayankgrd's picture
Add 2 files
c7d8cdc verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Matrix Pro</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.task-card {
transition: all 0.3s ease;
}
.task-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.kanban-column {
min-height: 400px;
}
.calendar-day {
transition: all 0.2s ease;
}
.calendar-day:hover {
background-color: #f3f4f6;
}
.calendar-day.has-tasks::after {
content: '';
display: block;
width: 6px;
height: 6px;
background-color: #3b82f6;
border-radius: 50%;
margin: 2px auto 0;
}
.active-tab {
border-bottom: 3px solid #3b82f6;
font-weight: 600;
}
[draggable="true"] {
cursor: move;
}
.kanban-column.highlight {
background-color: #f0f9ff;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="mb-8">
<h1 class="text-3xl font-bold text-gray-800">Task Matrix Pro</h1>
<p class="text-gray-600">Organize your tasks with Eisenhower Matrix</p>
</header>
<!-- Navigation Tabs -->
<div class="flex border-b border-gray-200 mb-6">
<button id="matrix-tab" class="px-4 py-2 active-tab">Matrix View</button>
<button id="kanban-tab" class="px-4 py-2">Kanban Board</button>
<button id="calendar-tab" class="px-4 py-2">Calendar</button>
</div>
<!-- Matrix View -->
<div id="matrix-view" class="view-content">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<!-- Task Input Form -->
<div class="bg-white p-4 rounded-lg shadow">
<h2 class="text-xl font-semibold mb-4">Add New Task</h2>
<form id="task-form" class="space-y-4">
<div>
<label for="task-title" class="block text-sm font-medium text-gray-700">Task Title</label>
<input type="text" id="task-title" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 p-2 border">
</div>
<div>
<label for="task-description" class="block text-sm font-medium text-gray-700">Description</label>
<textarea id="task-description" rows="2" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 p-2 border"></textarea>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700">Urgency</label>
<div class="mt-1 flex space-x-4">
<label class="inline-flex items-center">
<input type="radio" name="urgency" value="urgent" class="h-4 w-4 text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Urgent</span>
</label>
<label class="inline-flex items-center">
<input type="radio" name="urgency" value="not-urgent" class="h-4 w-4 text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Not Urgent</span>
</label>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Importance</label>
<div class="mt-1 flex space-x-4">
<label class="inline-flex items-center">
<input type="radio" name="importance" value="important" class="h-4 w-4 text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Important</span>
</label>
<label class="inline-flex items-center">
<input type="radio" name="importance" value="not-important" class="h-4 w-4 text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">Not Important</span>
</label>
</div>
</div>
</div>
<div>
<label for="task-due" class="block text-sm font-medium text-gray-700">Due Date</label>
<input type="date" id="task-due" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 p-2 border">
</div>
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Add Task
</button>
</form>
</div>
<!-- Eisenhower Matrix Explanation -->
<div class="bg-white p-4 rounded-lg shadow">
<h2 class="text-xl font-semibold mb-4">Eisenhower Matrix Guide</h2>
<div class="grid grid-cols-2 gap-2">
<div class="bg-red-100 p-3 rounded">
<h3 class="font-medium text-red-800">Urgent & Important</h3>
<p class="text-sm text-red-700">Do these tasks immediately</p>
</div>
<div class="bg-yellow-100 p-3 rounded">
<h3 class="font-medium text-yellow-800">Important, Not Urgent</h3>
<p class="text-sm text-yellow-700">Schedule these tasks</p>
</div>
<div class="bg-blue-100 p-3 rounded">
<h3 class="font-medium text-blue-800">Urgent, Not Important</h3>
<p class="text-sm text-blue-700">Delegate if possible</p>
</div>
<div class="bg-green-100 p-3 rounded">
<h3 class="font-medium text-green-800">Not Urgent, Not Important</h3>
<p class="text-sm text-green-700">Consider eliminating</p>
</div>
</div>
<div class="mt-4 text-sm text-gray-600">
<p>The Eisenhower Matrix helps you prioritize tasks based on urgency and importance. This method was popularized by US President Dwight D. Eisenhower.</p>
</div>
</div>
</div>
<!-- Task Matrix -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Quadrant 1: Urgent & Important -->
<div class="bg-red-50 p-4 rounded-lg shadow">
<h2 class="text-lg font-semibold text-red-800 mb-4 flex items-center">
<i class="fas fa-exclamation-triangle mr-2"></i> Urgent & Important
</h2>
<div id="quadrant-1" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
<!-- Quadrant 2: Important, Not Urgent -->
<div class="bg-yellow-50 p-4 rounded-lg shadow">
<h2 class="text-lg font-semibold text-yellow-800 mb-4 flex items-center">
<i class="fas fa-calendar-check mr-2"></i> Important, Not Urgent
</h2>
<div id="quadrant-2" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
<!-- Quadrant 3: Urgent, Not Important -->
<div class="bg-blue-50 p-4 rounded-lg shadow">
<h2 class="text-lg font-semibold text-blue-800 mb-4 flex items-center">
<i class="fas fa-share-square mr-2"></i> Urgent, Not Important
</h2>
<div id="quadrant-3" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
<!-- Quadrant 4: Not Urgent, Not Important -->
<div class="bg-green-50 p-4 rounded-lg shadow">
<h2 class="text-lg font-semibold text-green-800 mb-4 flex items-center">
<i class="fas fa-trash-alt mr-2"></i> Not Urgent, Not Important
</h2>
<div id="quadrant-4" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
</div>
</div>
<!-- Kanban Board View (hidden by default) -->
<div id="kanban-view" class="view-content hidden">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Backlog Column -->
<div class="bg-gray-100 p-4 rounded-lg shadow kanban-column"
id="backlog-column"
ondrop="handleDrop(event, 'backlog')"
ondragover="handleDragOver(event)"
ondragenter="handleDragEnter(event)"
ondragleave="handleDragLeave(event)">
<h2 class="text-lg font-semibold text-gray-800 mb-4 flex items-center justify-between">
<span><i class="fas fa-clipboard-list mr-2"></i> Backlog</span>
<span id="backlog-count" class="bg-gray-200 text-gray-700 text-xs font-medium px-2.5 py-0.5 rounded-full">0</span>
</h2>
<div id="backlog-tasks" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
<!-- In Progress Column -->
<div class="bg-blue-100 p-4 rounded-lg shadow kanban-column"
id="progress-column"
ondrop="handleDrop(event, 'progress')"
ondragover="handleDragOver(event)"
ondragenter="handleDragEnter(event)"
ondragleave="handleDragLeave(event)">
<h2 class="text-lg font-semibold text-blue-800 mb-4 flex items-center justify-between">
<span><i class="fas fa-spinner mr-2"></i> In Progress</span>
<span id="progress-count" class="bg-blue-200 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded-full">0</span>
</h2>
<div id="progress-tasks" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
<!-- Done Column -->
<div class="bg-green-100 p-4 rounded-lg shadow kanban-column"
id="done-column"
ondrop="handleDrop(event, 'done')"
ondragover="handleDragOver(event)"
ondragenter="handleDragEnter(event)"
ondragleave="handleDragLeave(event)">
<h2 class="text-lg font-semibold text-green-800 mb-4 flex items-center justify-between">
<span><i class="fas fa-check-circle mr-2"></i> Done</span>
<span id="done-count" class="bg-green-200 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded-full">0</span>
</h2>
<div id="done-tasks" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
</div>
</div>
</div>
<!-- Calendar View (hidden by default) -->
<div id="calendar-view" class="view-content hidden">
<div class="bg-white p-4 rounded-lg shadow mb-6">
<div class="flex items-center justify-between mb-4">
<button id="prev-month" class="p-2 rounded-full hover:bg-gray-100">
<i class="fas fa-chevron-left"></i>
</button>
<h2 id="current-month" class="text-xl font-semibold">July 2023</h2>
<button id="next-month" class="p-2 rounded-full hover:bg-gray-100">
<i class="fas fa-chevron-right"></i>
</button>
</div>
<div class="grid grid-cols-7 gap-1">
<div class="text-center font-medium text-gray-500 py-2">Sun</div>
<div class="text-center font-medium text-gray-500 py-2">Mon</div>
<div class="text-center font-medium text-gray-500 py-2">Tue</div>
<div class="text-center font-medium text-gray-500 py-2">Wed</div>
<div class="text-center font-medium text-gray-500 py-2">Thu</div>
<div class="text-center font-medium text-gray-500 py-2">Fri</div>
<div class="text-center font-medium text-gray-500 py-2">Sat</div>
</div>
<div id="calendar-days" class="grid grid-cols-7 gap-1">
<!-- Calendar days will be generated here -->
</div>
</div>
<div id="day-tasks" class="bg-white p-4 rounded-lg shadow">
<h2 id="selected-day" class="text-xl font-semibold mb-4">Select a date to view tasks</h2>
<div id="day-tasks-list" class="space-y-3">
<!-- Tasks for selected day will appear here -->
</div>
</div>
</div>
</div>
<script>
// Task data structure
let tasks = [];
let currentDate = new Date();
let selectedDay = null;
let draggedTaskId = null;
// DOM Elements
const taskForm = document.getElementById('task-form');
const matrixView = document.getElementById('matrix-view');
const kanbanView = document.getElementById('kanban-view');
const calendarView = document.getElementById('calendar-view');
const views = [matrixView, kanbanView, calendarView];
// Tab buttons
const matrixTab = document.getElementById('matrix-tab');
const kanbanTab = document.getElementById('kanban-tab');
const calendarTab = document.getElementById('calendar-tab');
const tabs = [matrixTab, kanbanTab, calendarTab];
// Calendar elements
const prevMonthBtn = document.getElementById('prev-month');
const nextMonthBtn = document.getElementById('next-month');
const currentMonthEl = document.getElementById('current-month');
const calendarDaysEl = document.getElementById('calendar-days');
const selectedDayEl = document.getElementById('selected-day');
const dayTasksListEl = document.getElementById('day-tasks-list');
// Initialize the app
document.addEventListener('DOMContentLoaded', function() {
// Load tasks from localStorage if available
const savedTasks = localStorage.getItem('tasks');
if (savedTasks) {
tasks = JSON.parse(savedTasks);
} else {
// Initialize with some sample tasks if none exist
tasks = [
{
id: '1',
title: 'Complete project proposal',
description: 'Finish writing the project proposal document',
dueDate: formatDateForInput(new Date()),
urgency: 'urgent',
importance: 'important',
status: 'progress',
createdAt: new Date().toISOString()
},
{
id: '2',
title: 'Schedule team meeting',
description: 'Plan next week\'s team meeting',
dueDate: formatDateForInput(new Date(Date.now() + 86400000 * 2)),
urgency: 'not-urgent',
importance: 'important',
status: 'backlog',
createdAt: new Date().toISOString()
}
];
saveTasks();
}
// Set up event listeners
setupEventListeners();
// Render initial views
renderMatrixView();
renderKanbanView();
renderCalendar();
// Set matrix view as default
switchView(0);
});
// Set up event listeners
function setupEventListeners() {
// Task form submission
taskForm.addEventListener('submit', function(e) {
e.preventDefault();
addNewTask();
});
// Tab switching
tabs.forEach((tab, index) => {
tab.addEventListener('click', () => switchView(index));
});
// Calendar navigation
prevMonthBtn.addEventListener('click', () => {
currentDate.setMonth(currentDate.getMonth() - 1);
renderCalendar();
});
nextMonthBtn.addEventListener('click', () => {
currentDate.setMonth(currentDate.getMonth() + 1);
renderCalendar();
});
}
// Switch between views
function switchView(index) {
views.forEach(view => view.classList.add('hidden'));
views[index].classList.remove('hidden');
tabs.forEach(tab => tab.classList.remove('active-tab'));
tabs[index].classList.add('active-tab');
// Update specific views when switched to
if (index === 1) renderKanbanView();
if (index === 2) renderCalendar();
}
// Add a new task
function addNewTask() {
const title = document.getElementById('task-title').value.trim();
const description = document.getElementById('task-description').value.trim();
const dueDate = document.getElementById('task-due').value;
const urgency = document.querySelector('input[name="urgency"]:checked')?.value;
const importance = document.querySelector('input[name="importance"]:checked')?.value;
if (!title || !urgency || !importance) {
alert('Please fill in all required fields');
return;
}
const newTask = {
id: Date.now().toString(),
title,
description,
dueDate,
urgency,
importance,
status: 'backlog', // Default status for Kanban
createdAt: new Date().toISOString()
};
tasks.push(newTask);
saveTasks();
renderMatrixView();
renderKanbanView();
renderCalendar();
// Reset form
taskForm.reset();
}
// Save tasks to localStorage
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Render the matrix view
function renderMatrixView() {
const quadrants = {
'quadrant-1': { urgency: 'urgent', importance: 'important' },
'quadrant-2': { urgency: 'not-urgent', importance: 'important' },
'quadrant-3': { urgency: 'urgent', importance: 'not-important' },
'quadrant-4': { urgency: 'not-urgent', importance: 'not-important' }
};
// Clear all quadrants
for (const quadrantId in quadrants) {
document.getElementById(quadrantId).innerHTML = '';
}
// Add tasks to their respective quadrants
tasks.forEach(task => {
const { urgency, importance } = task;
let quadrantId = '';
if (urgency === 'urgent' && importance === 'important') {
quadrantId = 'quadrant-1';
} else if (urgency === 'not-urgent' && importance === 'important') {
quadrantId = 'quadrant-2';
} else if (urgency === 'urgent' && importance === 'not-important') {
quadrantId = 'quadrant-3';
} else {
quadrantId = 'quadrant-4';
}
const taskElement = createTaskElement(task, true);
document.getElementById(quadrantId).appendChild(taskElement);
});
}
// Render the kanban view
function renderKanbanView() {
const statuses = ['backlog', 'progress', 'done'];
const statusIds = ['backlog-tasks', 'progress-tasks', 'done-tasks'];
const countIds = ['backlog-count', 'progress-count', 'done-count'];
// Clear all columns
statusIds.forEach(id => {
document.getElementById(id).innerHTML = '';
});
// Update counts
statuses.forEach((status, index) => {
const count = tasks.filter(task => task.status === status).length;
document.getElementById(countIds[index]).textContent = count;
});
// Add tasks to their respective columns
tasks.forEach(task => {
let columnId = '';
switch(task.status) {
case 'backlog': columnId = 'backlog-tasks'; break;
case 'progress': columnId = 'progress-tasks'; break;
case 'done': columnId = 'done-tasks'; break;
}
const taskElement = createTaskElement(task, false);
taskElement.setAttribute('draggable', 'true');
taskElement.addEventListener('dragstart', (e) => {
draggedTaskId = task.id;
e.dataTransfer.setData('text/plain', task.id);
e.currentTarget.classList.add('opacity-50');
});
taskElement.addEventListener('dragend', (e) => {
e.currentTarget.classList.remove('opacity-50');
});
document.getElementById(columnId).appendChild(taskElement);
});
}
// Drag and drop handlers
function handleDragStart(e) {
draggedTaskId = e.target.dataset.id;
e.dataTransfer.setData('text/plain', draggedTaskId);
e.target.classList.add('opacity-50');
}
function handleDragEnd(e) {
e.target.classList.remove('opacity-50');
}
function handleDragOver(e) {
e.preventDefault();
}
function handleDragEnter(e) {
if (e.target.classList.contains('kanban-column')) {
e.target.classList.add('highlight');
}
}
function handleDragLeave(e) {
if (e.target.classList.contains('kanban-column')) {
e.target.classList.remove('highlight');
}
}
function handleDrop(e, newStatus) {
e.preventDefault();
e.target.classList.remove('highlight');
const taskId = e.dataTransfer.getData('text/plain');
const taskIndex = tasks.findIndex(task => task.id === taskId);
if (taskIndex !== -1) {
tasks[taskIndex].status = newStatus;
saveTasks();
renderKanbanView();
}
}
// Render the calendar
function renderCalendar() {
// Update month display
const options = { month: 'long', year: 'numeric' };
currentMonthEl.textContent = currentDate.toLocaleDateString('en-US', options);
// Get first day of month and total days
const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1).getDay();
const daysInMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0).getDate();
// Clear calendar
calendarDaysEl.innerHTML = '';
// Add empty cells for days before the first day of the month
for (let i = 0; i < firstDay; i++) {
const emptyCell = document.createElement('div');
emptyCell.className = 'h-12';
calendarDaysEl.appendChild(emptyCell);
}
// Add cells for each day of the month
for (let day = 1; day <= daysInMonth; day++) {
const dayCell = document.createElement('div');
dayCell.className = 'h-12 border border-gray-200 flex items-center justify-center calendar-day';
dayCell.textContent = day;
// Check if this day has tasks
const dateStr = `${currentDate.getFullYear()}-${(currentDate.getMonth() + 1).toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
const dayTasks = tasks.filter(task => task.dueDate === dateStr);
if (dayTasks.length > 0) {
dayCell.classList.add('has-tasks');
}
// Add click event to show tasks for this day
dayCell.addEventListener('click', () => {
selectedDay = dateStr;
showDayTasks(dateStr);
});
calendarDaysEl.appendChild(dayCell);
}
}
// Show tasks for a specific day
function showDayTasks(dateStr) {
const date = new Date(dateStr);
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
selectedDayEl.textContent = date.toLocaleDateString('en-US', options);
// Filter tasks for this day
const dayTasks = tasks.filter(task => task.dueDate === dateStr);
// Clear previous tasks
dayTasksListEl.innerHTML = '';
if (dayTasks.length === 0) {
dayTasksListEl.innerHTML = '<p class="text-gray-500">No tasks for this day</p>';
return;
}
// Add tasks to the list
dayTasks.forEach(task => {
const taskElement = createTaskElement(task, true);
dayTasksListEl.appendChild(taskElement);
});
}
// Create a task element
function createTaskElement(task, showDelete) {
const taskElement = document.createElement('div');
taskElement.className = 'bg-white p-3 rounded shadow task-card';
taskElement.id = `task-${task.id}`;
taskElement.dataset.id = task.id;
// Determine priority color
let priorityClass = '';
if (task.urgency === 'urgent' && task.importance === 'important') {
priorityClass = 'bg-red-100 text-red-800';
} else if (task.urgency === 'not-urgent' && task.importance === 'important') {
priorityClass = 'bg-yellow-100 text-yellow-800';
} else if (task.urgency === 'urgent' && task.importance === 'not-important') {
priorityClass = 'bg-blue-100 text-blue-800';
} else {
priorityClass = 'bg-green-100 text-green-800';
}
// Task content
taskElement.innerHTML = `
<div class="flex justify-between items-start mb-1">
<h3 class="font-medium">${task.title}</h3>
<span class="text-xs px-2 py-1 rounded-full ${priorityClass}">
${task.urgency === 'urgent' ? 'Urgent' : 'Not Urgent'},
${task.importance === 'important' ? 'Important' : 'Not Important'}
</span>
</div>
${task.description ? `<p class="text-sm text-gray-600 mb-2">${task.description}</p>` : ''}
${task.dueDate ? `<p class="text-xs text-gray-500"><i class="far fa-calendar-alt mr-1"></i> Due: ${formatDate(task.dueDate)}</p>` : ''}
<div class="mt-2 flex justify-between items-center">
<span class="text-xs text-gray-400">Created: ${formatDate(task.createdAt, true)}</span>
${showDelete ? `<button class="delete-task text-red-500 hover:text-red-700 text-sm" data-id="${task.id}">
<i class="fas fa-trash-alt"></i> Delete
</button>` : ''}
</div>
`;
// Add delete event listener if needed
if (showDelete) {
const deleteBtn = taskElement.querySelector('.delete-task');
deleteBtn.addEventListener('click', (e) => {
e.stopPropagation();
deleteTask(task.id);
});
}
return taskElement;
}
// Delete a task
function deleteTask(taskId) {
if (confirm('Are you sure you want to delete this task?')) {
tasks = tasks.filter(task => task.id !== taskId);
saveTasks();
renderMatrixView();
renderKanbanView();
renderCalendar();
// If viewing day tasks, update that view too
if (selectedDay) {
showDayTasks(selectedDay);
}
}
}
// Helper function to format dates
function formatDate(dateStr, includeTime = false) {
const date = new Date(dateStr);
if (includeTime) {
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
} else {
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}
}
// Helper function to format date for input field
function formatDateForInput(date) {
const d = new Date(date);
let month = '' + (d.getMonth() + 1);
let day = '' + d.getDate();
const year = d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return [year, month, day].join('-');
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=mayankgrd/deepseek-task-matrix" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>