// Task Manager Class class TaskManager { constructor() { this.tasks = this.loadTasks(); this.currentFilter = 'all'; this.init(); } init() { this.setupEventListeners(); this.renderTasks(); this.updateStats(); this.startReminderScheduler(); } setupEventListeners() { // Add task document.getElementById('addTaskBtn').addEventListener('click', () => this.addTask()); document.getElementById('taskInput').addEventListener('keypress', (e) => { if (e.key === 'Enter') this.addTask(); }); // Filter buttons document.querySelectorAll('.filter-btn').forEach(btn => { btn.addEventListener('click', (e) => { this.setFilter(e.target.dataset.filter); }); }); // Email modal document.getElementById('closeEmailModal').addEventListener('click', () => { document.getElementById('emailModal').classList.add('hidden'); }); // Reminder modal document.getElementById('closeReminderModal').addEventListener('click', () => { document.getElementById('reminderModal').classList.add('hidden'); this.currentReminderTaskId = null; }); document.getElementById('cancelReminder').addEventListener('click', () => { document.getElementById('reminderModal').classList.add('hidden'); this.currentReminderTaskId = null; }); document.getElementById('stopExistingReminder').addEventListener('click', () => { if (this.currentReminderTaskId) { const task = this.tasks.find(t => t.id === this.currentReminderTaskId); if (task) { task.hasReminder = false; task.reminderStopped = true; this.saveTasks(); this.renderTasks(); this.updateStats(); this.showToast('Reminder stopped', 'info'); } } document.getElementById('reminderModal').classList.add('hidden'); this.currentReminderTaskId = null; }); // Frequency buttons document.querySelectorAll('.frequency-btn').forEach(btn => { btn.addEventListener('click', (e) => { const frequency = e.currentTarget.dataset.frequency; this.setReminderFrequency(frequency); }); }); // Close modals on outside click document.getElementById('emailModal').addEventListener('click', (e) => { if (e.target.id === 'emailModal') { document.getElementById('emailModal').classList.add('hidden'); } }); document.getElementById('reminderModal').addEventListener('click', (e) => { if (e.target.id === 'reminderModal') { document.getElementById('reminderModal').classList.add('hidden'); this.currentReminderTaskId = null; } }); } addTask() { const taskInput = document.getElementById('taskInput'); const emailInput = document.getElementById('emailInput'); const taskText = taskInput.value.trim(); const email = emailInput.value.trim(); if (!taskText) { this.showToast('Please enter a task', 'error'); return; } if (!email || !this.isValidEmail(email)) { this.showToast('Please enter a valid email address', 'error'); return; } const task = { id: Date.now(), text: taskText, email: email, completed: false, hasReminder: false, reminderStopped: false, createdAt: new Date().toISOString(), completedAt: null }; this.tasks.push(task); this.saveTasks(); this.renderTasks(); this.updateStats(); // Clear inputs taskInput.value = ''; emailInput.value = ''; this.showToast('Task added successfully!', 'success'); } toggleTask(id) { const task = this.tasks.find(t => t.id === id); if (task) { task.completed = !task.completed; task.completedAt = task.completed ? new Date().toISOString() : null; // When task is completed, automatically stop reminders if (task.completed) { task.hasReminder = false; task.reminderStopped = true; } this.saveTasks(); this.renderTasks(); this.updateStats(); if (task.completed) { this.showToast('Task completed! Great job! 🎉', 'success'); } else { // If unchecking a completed task, reset reminder status task.reminderStopped = false; this.showToast('Task marked as incomplete', 'info'); } } } toggleReminder(id) { const task = this.tasks.find(t => t.id === id); if (task) { if (task.completed) { this.showToast('Cannot set reminder for completed task', 'error'); return; } this.currentReminderTaskId = id; if (task.hasReminder && !task.reminderStopped) { // Show stop reminder option document.getElementById('reminderModal').classList.remove('hidden'); document.getElementById('stopExistingReminder').classList.remove('hidden'); document.querySelectorAll('.frequency-btn').forEach(btn => btn.style.display = 'none'); } else { // Show frequency selection document.getElementById('reminderModal').classList.remove('hidden'); document.getElementById('stopExistingReminder').classList.add('hidden'); document.querySelectorAll('.frequency-btn').forEach(btn => btn.style.display = 'block'); } } setReminderFrequency(frequency) { if (!this.currentReminderTaskId) return; const task = this.tasks.find(t => t.id === this.currentReminderTaskId); if (task) { task.hasReminder = true; task.reminderStopped = false; task.reminderFrequency = frequency; const frequencyText = frequency === 'daily' ? 'daily' : frequency === 'weekly' ? 'weekly' : 'monthly'; this.showToast(`Reminder set! You'll receive ${frequencyText} email notifications`, 'success'); this.showEmailPreview(task); this.saveTasks(); this.renderTasks(); this.updateStats(); } document.getElementById('reminderModal').classList.add('hidden'); this.currentReminderTaskId = null; } deleteTask(id) { if (confirm('Are you sure you want to delete this task?')) { this.tasks = this.tasks.filter(t => t.id !== id); this.saveTasks(); this.renderTasks(); this.updateStats(); this.showToast('Task deleted', 'info'); } } setFilter(filter) { this.currentFilter = filter; // Update button styles document.querySelectorAll('.filter-btn').forEach(btn => { if (btn.dataset.filter === filter) { btn.className = 'filter-btn px-4 py-2 bg-primary-500 text-white rounded-lg transition-colors'; } else { btn.className = 'filter-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors'; } }); this.renderTasks(); } getFilteredTasks() { switch (this.currentFilter) { case 'pending': return this.tasks.filter(t => !t.completed); case 'completed': return this.tasks.filter(t => t.completed); case 'reminders': return this.tasks.filter(t => t.hasReminder && !t.reminderStopped && !t.completed); default: return this.tasks; } } renderTasks() { const container = document.getElementById('tasksContainer'); const emptyState = document.getElementById('emptyState'); const filteredTasks = this.getFilteredTasks(); if (filteredTasks.length === 0) { container.innerHTML = ''; emptyState.style.display = 'block'; return; } emptyState.style.display = 'none'; container.innerHTML = filteredTasks.map(task => ` `).join(''); // Re-initialize feather icons for new elements feather.replace(); } updateStats() { const total = this.tasks.length; const completed = this.tasks.filter(t => t.completed).length; const pending = total - completed; const reminders = this.tasks.filter(t => t.hasReminder && !t.reminderStopped && !t.completed).length; document.getElementById('totalTasks').textContent = total; document.getElementById('completedTasks').textContent = completed; document.getElementById('pendingTasks').textContent = pending; document.getElementById('activeReminders').textContent = reminders; } showEmailPreview(task) { document.getElementById('emailTo').textContent = task.email; document.getElementById('emailSubject').textContent = task.text; document.getElementById('emailTask').textContent = task.text; document.getElementById('emailModal').classList.remove('hidden'); } startReminderScheduler() { // Check for reminders every minute setInterval(() => { this.tasks.forEach(task => { if (task.hasReminder && !task.reminderStopped && !task.completed) { const now = new Date(); const lastReminder = task.lastReminder ? new Date(task.lastReminder) : null; let shouldSend = false; if (!lastReminder) { // First reminder shouldSend = true; } else { const timeDiff = now - lastReminder; const daysDiff = timeDiff / (1000 * 60 * 60 * 24); switch (task.reminderFrequency) { case 'daily': shouldSend = daysDiff >= 1; break; case 'weekly': shouldSend = daysDiff >= 7; break; case 'monthly': shouldSend = daysDiff >= 30; break; } } if (shouldSend) { // In a real app, this would send an email console.log(`Sending ${task.reminderFrequency} reminder for task: ${task.text} to ${task.email}`); this.showToast(`Reminder: ${task.text}`, 'info'); task.lastReminder = now.toISOString(); this.saveTasks(); } } }); }, 60000); // Check every minute } showToast(message, type = 'info') { const toast = document.createElement('div'); const bgColor = type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : 'bg-blue-500'; toast.className = `fixed bottom-4 right-4 ${bgColor} text-white px-6 py-3 rounded-lg shadow-lg z-50 flex items-center gap-2 task-card-enter`; const icon = type === 'success' ? 'check-circle' : type === 'error' ? 'alert-circle' : 'info'; toast.innerHTML = ` ${message} `; document.body.appendChild(toast); feather.replace(); setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, 3000); } isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } saveTasks() { localStorage.setItem('tasks', JSON.stringify(this.tasks)); } loadTasks() { const saved = localStorage.getItem('tasks'); return saved ? JSON.parse(saved) : []; } } // Custom event delegation for dynamic task cards document.addEventListener('click', (e) => { const toggleBtn = e.target.closest('[data-action="toggle"]'); const reminderBtn = e.target.closest('[data-action="reminder"]'); const deleteBtn = e.target.closest('[data-action="delete"]'); if (toggleBtn) { const card = e.target.closest('task-card'); if (card) { taskManager.toggleTask(parseInt(card.getAttribute('id')))); } else if (reminderBtn) { const card = e.target.closest('task-card'); if (card) { taskManager.toggleReminder(parseInt(card.getAttribute('id')))); } else if (deleteBtn) { const card = e.target.closest('task-card'); if (card) { taskManager.deleteTask(parseInt(card.getAttribute('id')))); } } }); // Initialize the app const taskManager = new TaskManager();