task-tracker-pro / index.html
marinhows's picture
altere por dia e por semana, e crie uma forma disso ficar armazenado por pelo menos 7 dias e quem é responsavel
19d67fa verified
Raw History Blame Contribute Delete
22.1 kB
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Tracker Pro</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
},
secondary: {
50: '#fdf2f8',
100: '#fce7f3',
200: '#fbcfe8',
300: '#f9a8d4',
400: '#f472b6',
500: '#ec4899',
600: '#db2777',
700: '#be185d',
800: '#9d174d',
900: '#831843',
}
}
}
}
}
</script>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="mb-12 text-center">
<h1 class="text-4xl font-bold text-primary-700 mb-2">Task Tracker Pro ✨</h1>
<p class="text-gray-600">Organize suas tarefas diárias e semanais</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Daily Tasks Section -->
<section class="bg-white rounded-xl shadow-lg p-6">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i data-feather="sun" class="mr-2 text-primary-500"></i>
Tarefas Diárias
</h2>
<button id="addDailyTaskBtn" class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg flex items-center transition duration-300">
<i data-feather="plus-circle" class="mr-1"></i>
Nova Tarefa
</button>
</div>
<!-- Add Daily Task Form -->
<div id="dailyTaskForm" class="mb-6 hidden">
<div class="bg-blue-50 rounded-lg p-4 border border-blue-200">
<input type="text" id="dailyTaskInput" placeholder="Digite sua nova tarefa..." class="w-full p-3 rounded-lg border border-gray-300 mb-3 focus:outline-none focus:ring-2 focus:ring-primary-300">
<input type="text" id="dailyAssigneeInput" placeholder="Responsável pela tarefa..." class="w-full p-3 rounded-lg border border-gray-300 mb-3 focus:outline-none focus:ring-2 focus:ring-primary-300">
<div class="flex justify-end space-x-2">
<button id="cancelDailyTaskBtn" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition">Cancelar</button>
<button id="saveDailyTaskBtn" class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg transition duration-300">Adicionar</button>
</div>
</div>
</div>
<!-- Daily Task List -->
<div id="dailyTaskList" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
<!-- Empty State -->
<div id="emptyDailyTaskState" class="hidden text-center py-12">
<i data-feather="check-circle" class="mx-auto text-gray-300 mb-4" style="width: 64px; height: 64px;"></i>
<h3 class="text-xl font-medium text-gray-500 mb-2">Nenhuma tarefa diária</h3>
<p class="text-gray-400">Adicione tarefas para hoje!</p>
</div>
</section>
<!-- Weekly Tasks Section -->
<section class="bg-white rounded-xl shadow-lg p-6">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i data-feather="calendar" class="mr-2 text-secondary-500"></i>
Tarefas Semanais
</h2>
<button id="addWeeklyTaskBtn" class="bg-secondary-500 hover:bg-secondary-600 text-white px-4 py-2 rounded-lg flex items-center transition duration-300">
<i data-feather="plus-circle" class="mr-1"></i>
Nova Tarefa
</button>
</div>
<!-- Add Weekly Task Form -->
<div id="weeklyTaskForm" class="mb-6 hidden">
<div class="bg-purple-50 rounded-lg p-4 border border-purple-200">
<input type="text" id="weeklyTaskInput" placeholder="Digite sua nova tarefa..." class="w-full p-3 rounded-lg border border-gray-300 mb-3 focus:outline-none focus:ring-2 focus:ring-secondary-300">
<input type="text" id="weeklyAssigneeInput" placeholder="Responsável pela tarefa..." class="w-full p-3 rounded-lg border border-gray-300 mb-3 focus:outline-none focus:ring-2 focus:ring-secondary-300">
<div class="flex justify-end space-x-2">
<button id="cancelWeeklyTaskBtn" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition">Cancelar</button>
<button id="saveWeeklyTaskBtn" class="bg-secondary-500 hover:bg-secondary-600 text-white px-4 py-2 rounded-lg transition duration-300">Adicionar</button>
</div>
</div>
</div>
<!-- Weekly Task List -->
<div id="weeklyTaskList" class="space-y-3">
<!-- Tasks will be added here dynamically -->
</div>
<!-- Empty State -->
<div id="emptyWeeklyTaskState" class="hidden text-center py-12">
<i data-feather="check-circle" class="mx-auto text-gray-300 mb-4" style="width: 64px; height: 64px;"></i>
<h3 class="text-xl font-medium text-gray-500 mb-2">Nenhuma tarefa semanal</h3>
<p class="text-gray-400">Adicione tarefas para esta semana!</p>
</div>
</section>
<!-- Task List -->
<div id="taskList" class="space-y-3">
<!-- Tasks will be added here dynamically -->
<div class="task-item bg-gray-50 p-4 rounded-lg border border-gray-200 flex justify-between items-center">
<div class="flex items-center">
<input type="checkbox" class="mr-3 h-5 w-5 text-primary-500 rounded focus:ring-primary-400">
<span class="task-text">Finalizar relatório mensal</span>
</div>
<button class="delete-task text-gray-400 hover:text-red-500">
<i data-feather="trash-2"></i>
</button>
</div>
<div class="task-item bg-gray-50 p-4 rounded-lg border border-gray-200 flex justify-between items-center">
<div class="flex items-center">
<input type="checkbox" class="mr-3 h-5 w-5 text-primary-500 rounded focus:ring-primary-400" checked>
<span class="task-text line-through text-gray-500">Reunião com equipe de desenvolvimento</span>
</div>
<button class="delete-task text-gray-400 hover:text-red-500">
<i data-feather="trash-2"></i>
</button>
</div>
<div class="task-item bg-gray-50 p-4 rounded-lg border border-gray-200 flex justify-between items-center">
<div class="flex items-center">
<input type="checkbox" class="mr-3 h-5 w-5 text-primary-500 rounded focus:ring-primary-400">
<span class="task-text">Preparar apresentação para cliente</span>
</div>
<button class="delete-task text-gray-400 hover:text-red-500">
<i data-feather="trash-2"></i>
</button>
</div>
</div>
<!-- Empty State -->
<div id="emptyTaskState" class="hidden text-center py-12">
<i data-feather="check-circle" class="mx-auto text-gray-300 mb-4" style="width: 64px; height: 64px;"></i>
<h3 class="text-xl font-medium text-gray-500 mb-2">Nenhuma tarefa pendente</h3>
<p class="text-gray-400">Você completou todas as suas tarefas!</p>
</div>
</section>
<!-- History Section -->
<section class="bg-white rounded-xl shadow-lg p-6">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i data-feather="clock" class="mr-2 text-green-500"></i>
Histórico (7 dias)
</h2>
<button id="clearHistoryBtn" class="text-sm bg-green-500 hover:bg-green-600 text-white px-3 py-1 rounded-lg flex items-center transition duration-300">
<i data-feather="trash-2" class="mr-1"></i>
Limpar
</button>
</div>
<!-- History List -->
<div id="historyList" class="space-y-3 max-h-[500px] overflow-y-auto pr-2">
<!-- History items will be added here dynamically -->
</div>
<!-- Empty History State -->
<div id="emptyHistoryState" class="hidden text-center py-12">
<i data-feather="file-text" class="mx-auto text-gray-300 mb-4" style="width: 64px; height: 64px;"></i>
<h3 class="text-xl font-medium text-gray-500 mb-2">Histórico vazio</h3>
<p class="text-gray-400">Suas tarefas concluídas aparecerão aqui</p>
</div>
</section>
</div>
</div>
<script>
// Initialize Feather Icons
feather.replace();
// DOM Elements - Daily Tasks
const addDailyTaskBtn = document.getElementById('addDailyTaskBtn');
const dailyTaskForm = document.getElementById('dailyTaskForm');
const cancelDailyTaskBtn = document.getElementById('cancelDailyTaskBtn');
const saveDailyTaskBtn = document.getElementById('saveDailyTaskBtn');
const dailyTaskInput = document.getElementById('dailyTaskInput');
const dailyAssigneeInput = document.getElementById('dailyAssigneeInput');
const dailyTaskList = document.getElementById('dailyTaskList');
// DOM Elements - Weekly Tasks
const addWeeklyTaskBtn = document.getElementById('addWeeklyTaskBtn');
const weeklyTaskForm = document.getElementById('weeklyTaskForm');
const cancelWeeklyTaskBtn = document.getElementById('cancelWeeklyTaskBtn');
const saveWeeklyTaskBtn = document.getElementById('saveWeeklyTaskBtn');
const weeklyTaskInput = document.getElementById('weeklyTaskInput');
const weeklyAssigneeInput = document.getElementById('weeklyAssigneeInput');
const weeklyTaskList = document.getElementById('weeklyTaskList');
// DOM Elements - History
const historyList = document.getElementById('historyList');
const clearHistoryBtn = document.getElementById('clearHistoryBtn');
// DOM Elements - Empty States
const emptyDailyTaskState = document.getElementById('emptyDailyTaskState');
const emptyWeeklyTaskState = document.getElementById('emptyWeeklyTaskState');
const emptyHistoryState = document.getElementById('emptyHistoryState');
// Data storage
let tasks = JSON.parse(localStorage.getItem('tasks')) || {
daily: [],
weekly: [],
history: []
};
// Initialize the app
function init() {
renderTasks();
updateEmptyStates();
setupEventListeners();
}
// Set up event listeners
function setupEventListeners() {
// Daily Tasks
addDailyTaskBtn.addEventListener('click', () => {
dailyTaskForm.classList.toggle('hidden');
dailyTaskInput.focus();
});
cancelDailyTaskBtn.addEventListener('click', () => {
dailyTaskForm.classList.add('hidden');
dailyTaskInput.value = '';
dailyAssigneeInput.value = '';
});
saveDailyTaskBtn.addEventListener('click', saveDailyTask);
// Weekly Tasks
addWeeklyTaskBtn.addEventListener('click', () => {
weeklyTaskForm.classList.toggle('hidden');
weeklyTaskInput.focus();
});
cancelWeeklyTaskBtn.addEventListener('click', () => {
weeklyTaskForm.classList.add('hidden');
weeklyTaskInput.value = '';
weeklyAssigneeInput.value = '';
});
saveWeeklyTaskBtn.addEventListener('click', saveWeeklyTask);
// History
clearHistoryBtn.addEventListener('click', clearHistory);
}
// Save daily task
function saveDailyTask() {
const taskText = dailyTaskInput.value.trim();
const assignee = dailyAssigneeInput.value.trim();
if (taskText) {
const task = {
id: Date.now(),
text: taskText,
assignee: assignee || 'Não atribuído',
completed: false,
createdAt: new Date().toISOString()
};
tasks.daily.push(task);
saveTasks();
renderTasks();
dailyTaskInput.value = '';
dailyAssigneeInput.value = '';
dailyTaskForm.classList.add('hidden');
updateEmptyStates();
}
}
// Save weekly task
function saveWeeklyTask() {
const taskText = weeklyTaskInput.value.trim();
const assignee = weeklyAssigneeInput.value.trim();
if (taskText) {
const task = {
id: Date.now(),
text: taskText,
assignee: assignee || 'Não atribuído',
completed: false,
createdAt: new Date().toISOString()
};
tasks.weekly.push(task);
saveTasks();
renderTasks();
weeklyTaskInput.value = '';
weeklyAssigneeInput.value = '';
weeklyTaskForm.classList.add('hidden');
updateEmptyStates();
}
}
// Render all tasks
function renderTasks() {
renderDailyTasks();
renderWeeklyTasks();
renderHistory();
}
// Render daily tasks
function renderDailyTasks() {
dailyTaskList.innerHTML = '';
tasks.daily.forEach(task => {
const taskElement = createTaskElement(task, 'daily');
dailyTaskList.appendChild(taskElement);
});
}
// Render weekly tasks
function renderWeeklyTasks() {
weeklyTaskList.innerHTML = '';
tasks.weekly.forEach(task => {
const taskElement = createTaskElement(task, 'weekly');
weeklyTaskList.appendChild(taskElement);
});
}
// Create task element
function createTaskElement(task, type) {
const taskElement = document.createElement('div');
taskElement.className = 'task-item bg-gray-50 p-4 rounded-lg border border-gray-200 flex justify-between items-center';
taskElement.innerHTML = `
<div class="flex items-center">
<input type="checkbox" ${task.completed ? 'checked' : ''} class="mr-3 h-5 w-5 text-${type === 'daily' ? 'primary' : 'secondary'}-500 rounded focus:ring-${type === 'daily' ? 'primary' : 'secondary'}-400">
<div>
<span class="task-text ${task.completed ? 'line-through text-gray-500' : 'text-gray-800'}">${task.text}</span>
<p class="text-xs text-gray-500 mt-1">${task.assignee}</p>
</div>
</div>
<button class="delete-task text-gray-400 hover:text-red-500">
<i data-feather="trash-2"></i>
</button>
`;
// Add event listeners
const checkbox = taskElement.querySelector('input[type="checkbox"]');
const deleteBtn = taskElement.querySelector('.delete-task');
checkbox.addEventListener('change', (e) => toggleTaskCompletion(task.id, type, e.target.checked));
deleteBtn.addEventListener('click', () => deleteTask(task.id, type));
feather.replace();
return taskElement;
}
// Toggle task completion
function toggleTaskCompletion taskId, type, completed) {
const taskList = type === 'daily' ? tasks.daily : tasks.weekly;
const task = taskList.find(t => t.id === taskId);
if (task) {
task.completed = completed;
// If completing task, add to history
if (completed) {
const historyItem = {
...task,
completedAt: new Date().toISOString()
};
tasks.history.unshift(historyItem);
// Keep only last 7 days of history
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
tasks.history = tasks.history.filter(item =>
new Date(item.completedAt) > sevenDaysAgo
);
}
saveTasks();
renderTasks();
updateEmptyStates();
}
}
// Delete task
function deleteTask(taskId, type) {
if (type === 'daily') {
tasks.daily = tasks.daily.filter(task => task.id !== taskId);
} else {
tasks.weekly = tasks.weekly.filter(task => task.id !== taskId);
}
saveTasks();
renderTasks();
updateEmptyStates();
}
// Render history
function renderHistory() {
historyList.innerHTML = '';
tasks.history.forEach(item => {
const historyElement = document.createElement('div');
historyElement.className = 'history-item bg-gray-50 p-4 rounded-lg border border-gray-200';
const completedDate = new Date(item.completedAt);
const dateStr = completedDate.toLocaleDateString('pt-BR', {
day: 'numeric',
month: 'long'
});
const timeStr = completedDate.toLocaleTimeString('pt-BR', {
hour: '2-digit',
minute: '2-digit'
});
historyElement.innerHTML = `
<div class="flex justify-between items-start">
<div>
<p class="font-medium text-gray-800">${item.text}</p>
<p class="text-xs text-gray-500 mt-1">${item.assignee}</p>
<p class="text-sm text-gray-500 mt-1">Completada em ${dateStr} às ${timeStr}</p>
</div>
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full">Concluída</span>
</div>
`;
historyList.appendChild(historyElement);
});
}
// Clear history
function clearHistory() {
if (confirm('Tem certeza que deseja limpar todo o histórico?')) {
tasks.history = [];
saveTasks();
renderTasks();
updateEmptyStates();
}
}
// Update empty states
function updateEmptyStates() {
emptyDailyTaskState.classList.toggle('hidden', tasks.daily.length > 0);
emptyWeeklyTaskState.classList.toggle('hidden', tasks.weekly.length > 0);
emptyHistoryState.classList.toggle('hidden', tasks.history.length > 0);
}
// Save tasks to localStorage
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Initialize the app
init();
</script>
</body>
</html>