/**
* Task Agent Specific Functions - Fixed Version
*/
class TaskAgent {
constructor() {
this.totalActions = 0;
this.tasks = [];
this.stats = {
total: 0,
overdue: 0,
dueToday: 0,
completed: 0,
inProgress: 0,
toDo: 0
};
// Set default API URL - you can override this
this.apiUrl = 'https://thecyberlearn.app.n8n.cloud/webhook/tasks';
this.init();
}
init() {
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => this.initializeAfterDOM());
} else {
this.initializeAfterDOM();
}
}
initializeAfterDOM() {
this.updateLastUpdated('lastUpdate');
this.initializeEventListeners();
// Load sample tasks if API URL is not configured
if (this.apiUrl.includes('your-n8n-instance.com')) {
console.log('Using sample data - configure apiUrl for real data');
this.loadSampleTasks();
} else {
this.loadTasks(); // Load tasks from API
}
}
updateLastUpdated(elementId) {
const element = document.getElementById(elementId);
if (element) {
element.textContent = new Date().toLocaleTimeString();
}
}
initializeEventListeners() {
const taskCommandInput = document.getElementById('taskCommand');
if (taskCommandInput) {
taskCommandInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.executeTaskCommand();
}
});
}
const searchInput = document.getElementById('taskSearchInput');
if (searchInput) {
searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.handleSearch();
}
});
}
}
setTaskCommand(command) {
const element = document.getElementById('taskCommand');
if (element) {
element.value = command;
this.executeTaskCommand();
}
}
async executeTaskCommand() {
const element = document.getElementById('taskCommand');
const command = element ? element.value : '';
if (!command) {
this.showToast('Please enter a command', 'warning');
return;
}
this.setButtonLoading('taskAiBtn', 'Processing...', 'fa-spinner fa-spin');
try {
// Simulate AI processing
await new Promise(resolve => setTimeout(resolve, 1500));
const response = this.generateTaskAIResponse(command);
this.showAIModal(response);
this.updateTaskStats();
this.updateLastUpdated('lastUpdate');
} catch (error) {
this.showToast('Error processing command: ' + error.message, 'error');
} finally {
this.restoreButton('taskAiBtn', 'Execute', 'fa-robot');
this.clearInput('taskCommand');
}
}
generateTaskAIResponse(command) {
const lowerCommand = command.toLowerCase();
if (lowerCommand.includes('overdue') || lowerCommand.includes('urgent')) {
return `
⚠️ Overdue Tasks Analysis
🚨 Immediate Action Required
Found ${this.stats.overdue} overdue tasks that need immediate attention
Website Security Audit - 2 days overdue
Client Presentation - Due today
💡 AI Recommendations
• Prioritize security audit first - highest business risk
• Delegate or reschedule lower priority tasks
• Block 2-hour focus time for urgent items
`;
}
return `
🤖 Task AI Response
Processing your request: "${command}"
I can help you with:
- • Smart task prioritization and scheduling
- • Deadline tracking and alerts
- • Progress analysis and reporting
- • Workload balancing and optimization
- • Task automation and workflows
`;
}
// Real API integration functions
async loadTasks(filters = {}) {
try {
this.showLoading(true);
const params = new URLSearchParams({
action: 'get_tasks',
...filters
});
console.log('Loading tasks from:', this.apiUrl);
const response = await fetch(`${this.apiUrl}?${params}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
if (data.success) {
this.tasks = data.tasks || [];
this.stats = data.stats || this.stats;
this.updateUI();
this.renderTasks();
console.log('✅ Tasks loaded successfully:', this.tasks.length);
} else {
throw new Error(data.message || 'Failed to load tasks');
}
} catch (error) {
console.error('❌ Error loading tasks:', error);
this.showError('Failed to load tasks: ' + error.message);
} finally {
this.showLoading(false);
}
}
// Load sample tasks for demonstration
loadSampleTasks() {
console.log('Loading sample tasks...');
this.tasks = [
{
id: 'task_1',
name: 'Website Security Audit',
description: 'Complete security assessment and vulnerability report',
dueDate: '02-01-2025',
dueDateFormatted: '2 days overdue',
timeEstimate: '3 hrs',
status: 'To Do',
priority: 'High',
priorityColor: 'red',
progress: 0,
type: 'Security',
isOverdue: true,
isDueToday: false
},
{
id: 'task_2',
name: 'Write Blog Article',
description: 'Article on "Top 5 AI Tools for Creators"',
dueDate: '06-01-2025',
dueDateFormatted: 'Due tomorrow',
timeEstimate: '2 hrs',
status: 'In Progress',
priority: 'Medium',
priorityColor: 'orange',
progress: 65,
type: 'Writing',
isOverdue: false,
isDueToday: false
},
{
id: 'task_3',
name: 'Design Landing Page',
description: 'Create a responsive landing page using Tailwind',
dueDate: '05-01-2025',
dueDateFormatted: 'Due today',
timeEstimate: '3 hrs',
status: 'To Do',
priority: 'Medium',
priorityColor: 'orange',
progress: 0,
type: 'Design',
isOverdue: false,
isDueToday: true
},
{
id: 'task_4',
name: 'Deploy Production Update',
description: 'Release v2.1.3 to production servers',
dueDate: '03-01-2025',
dueDateFormatted: 'Completed yesterday',
timeEstimate: '1 hr',
status: 'Done',
priority: 'High',
priorityColor: 'red',
progress: 100,
type: 'Development',
isOverdue: false,
isDueToday: false
}
];
this.stats = {
total: this.tasks.length,
overdue: this.tasks.filter(t => t.isOverdue).length,
dueToday: this.tasks.filter(t => t.isDueToday).length,
completed: this.tasks.filter(t => t.status === 'Done').length,
inProgress: this.tasks.filter(t => t.status === 'In Progress').length,
toDo: this.tasks.filter(t => t.status === 'To Do').length
};
this.updateUI();
this.renderTasks();
this.showLoading(false);
}
async searchTasks(query) {
if (!query.trim()) {
this.loadTasks();
return;
}
// Filter current tasks for demo
const filtered = this.tasks.filter(task =>
task.name.toLowerCase().includes(query.toLowerCase()) ||
task.description.toLowerCase().includes(query.toLowerCase())
);
this.renderFilteredTasks(filtered);
this.showToast(`Found ${filtered.length} tasks matching "${query}"`, 'info');
}
async filterTasks(status) {
console.log('Filtering by status:', status);
if (status === 'all') {
this.renderTasks();
return;
}
const statusMap = {
'todo': 'To Do',
'inprogress': 'In Progress',
'done': 'Done'
};
const targetStatus = statusMap[status] || status;
const filtered = this.tasks.filter(task => task.status === targetStatus);
this.renderFilteredTasks(filtered);
this.showToast(`Showing ${filtered.length} ${targetStatus} tasks`, 'info');
}
renderTasks() {
this.renderFilteredTasks(this.tasks);
}
renderFilteredTasks(tasks) {
const todoColumn = document.querySelector('#todoColumn .kanban-column');
const inProgressColumn = document.querySelector('#inProgressColumn .kanban-column');
const doneColumn = document.querySelector('#doneColumn .kanban-column');
if (!todoColumn || !inProgressColumn || !doneColumn) {
console.error('Kanban columns not found');
return;
}
// Clear existing tasks
todoColumn.innerHTML = '';
inProgressColumn.innerHTML = '';
doneColumn.innerHTML = '';
// Group tasks by status
const tasksByStatus = {
'To Do': [],
'In Progress': [],
'Done': []
};
tasks.forEach(task => {
if (tasksByStatus[task.status]) {
tasksByStatus[task.status].push(task);
}
});
// Render tasks in each column
Object.keys(tasksByStatus).forEach(status => {
const column = status === 'To Do' ? todoColumn :
status === 'In Progress' ? inProgressColumn : doneColumn;
tasksByStatus[status].forEach(task => {
column.appendChild(this.createTaskCard(task));
});
});
// Update column counts
this.updateColumnCounts(tasksByStatus);
}
createTaskCard(task) {
const card = document.createElement('div');
let cardClass = 'task-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer hover:shadow-md transition-all';
if (task.isOverdue) {
cardClass = 'task-card task-overdue bg-red-50 p-4 rounded-lg border border-red-200 cursor-pointer hover:shadow-md transition-all';
} else if (task.isDueToday) {
cardClass = 'task-card task-due-today bg-orange-50 p-4 rounded-lg border border-orange-200 cursor-pointer hover:shadow-md transition-all';
} else if (task.status === 'Done') {
cardClass = 'task-card task-completed bg-green-50 p-4 rounded-lg border border-green-200 cursor-pointer hover:shadow-md transition-all';
}
card.className = cardClass;
card.setAttribute('data-task-id', task.id);
const priorityBadgeColor = task.priority === 'High' ? 'red' :
task.priority === 'Medium' ? 'orange' : 'green';
let progressBar = '';
if (task.status === 'In Progress') {
progressBar = `
${task.progress}% complete
${task.dueDateFormatted}
`;
} else {
progressBar = `
${task.dueDateFormatted}
${task.type ? `${task.type}` : ''}
`;
}
card.innerHTML = `
${task.name}
${task.priority}
${task.description}
${progressBar}
${task.timeEstimate !== 'Not specified' ? `
Estimated: ${task.timeEstimate}
` : ''}
${task.status === 'Done' ? `
Completed
Yesterday
` : ''}
`;
// Add click handler for task details
card.addEventListener('click', () => this.showTaskDetails(task));
return card;
}
updateColumnCounts(tasksByStatus) {
const todoCountEl = document.querySelector('#todoColumn .text-gray-500');
const inProgressCountEl = document.querySelector('#inProgressColumn .text-gray-500');
const doneCountEl = document.querySelector('#doneColumn .text-gray-500');
if (todoCountEl) todoCountEl.textContent = tasksByStatus['To Do'].length;
if (inProgressCountEl) inProgressCountEl.textContent = tasksByStatus['In Progress'].length;
if (doneCountEl) doneCountEl.textContent = tasksByStatus['Done'].length;
}
updateUI() {
// Update stats dashboard
this.updateElement('overdueCount', this.stats.overdue);
this.updateElement('dueTodayCount', this.stats.dueToday);
this.updateElement('totalTasks', this.stats.total);
this.updateElement('completedToday', this.stats.completed);
this.updateLastUpdated('lastUpdate');
}
updateElement(id, value) {
const element = document.getElementById(id);
if (element) {
element.textContent = value;
}
}
showTaskDetails(task) {
const modalContent = `
${task.name}
${task.priority} Priority
Description
${task.description}
Due Date
${task.dueDateFormatted}
${task.status === 'In Progress' ? `
Progress
${task.progress}% Complete
` : ''}
Time Estimate
${task.timeEstimate}
`;
this.showAIModal(modalContent);
}
showLoading(show) {
const loadingElement = document.getElementById('loadingState');
const kanbanColumns = document.querySelectorAll('.kanban-column');
if (loadingElement) {
loadingElement.classList.toggle('hidden', !show);
}
if (show) {
kanbanColumns.forEach(column => {
column.innerHTML = ' Loading...
';
});
}
}
showError(message) {
const todoColumn = document.querySelector('#todoColumn .kanban-column');
if (todoColumn) {
todoColumn.innerHTML = `
Error Loading Tasks
${message}
`;
}
}
updateTaskStats() {
this.totalActions++;
}
// Utility functions
setButtonLoading(elementId, text, iconClass) {
const element = document.getElementById(elementId);
if (element) {
element.innerHTML = ` ${text}`;
element.disabled = true;
}
}
restoreButton(elementId, text, iconClass) {
const element = document.getElementById(elementId);
if (element) {
element.innerHTML = ` ${text}`;
element.disabled = false;
}
}
clearInput(elementId) {
const element = document.getElementById(elementId);
if (element) {
element.value = '';
}
}
showAIModal(content) {
const modal = document.getElementById('aiModal');
const responseDiv = document.getElementById('aiResponse');
if (modal && responseDiv) {
responseDiv.innerHTML = content;
modal.classList.remove('hidden');
}
}
hideAIModal() {
const modal = document.getElementById('aiModal');
if (modal) {
modal.classList.add('hidden');
}
}
showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `fixed top-4 right-4 z-50 max-w-sm w-full transform transition-all duration-300`;
const bgColor = {
success: 'bg-green-500',
error: 'bg-red-500',
warning: 'bg-yellow-500',
info: 'bg-blue-500'
}[type] || 'bg-gray-500';
const icon = {
success: 'fas fa-check-circle',
error: 'fas fa-exclamation-circle',
warning: 'fas fa-exclamation-triangle',
info: 'fas fa-info-circle'
}[type] || 'fas fa-info-circle';
toast.innerHTML = `
${message}
`;
document.body.appendChild(toast);
// Animate in
setTimeout(() => {
toast.style.transform = 'translateX(0)';
}, 100);
// Auto remove after 4 seconds
setTimeout(() => {
toast.style.transform = 'translateX(100%)';
setTimeout(() => {
if (toast.parentElement) {
toast.remove();
}
}, 300);
}, 4000);
}
// Quick action functions
createTask() {
this.showAIModal(`
✅ Create New Task
`);
}
async submitNewTask() {
const name = document.getElementById('newTaskName')?.value || '';
const description = document.getElementById('newTaskDescription')?.value || '';
const dueDate = document.getElementById('newTaskDue')?.value || '';
const priority = document.getElementById('newTaskPriority')?.value || 'Medium';
const timeEstimate = document.getElementById('newTaskTime')?.value || '1 hr';
if (!name.trim()) {
this.showToast('Please enter a task name', 'warning');
return;
}
try {
// In a real implementation, you would send this to your n8n workflow
// For now, we'll simulate success and add to local data
await new Promise(resolve => setTimeout(resolve, 1000));
// Add new task to local data for demo
const newTask = {
id: 'task_' + Date.now(),
name: name,
description: description || 'No description provided',
dueDate: dueDate,
dueDateFormatted: dueDate ? 'Due ' + new Date(dueDate).toLocaleDateString() : 'No due date',
timeEstimate: timeEstimate,
status: 'To Do',
priority: priority,
priorityColor: priority === 'High' ? 'red' : priority === 'Medium' ? 'orange' : 'green',
progress: 0,
type: 'General',
isOverdue: false,
isDueToday: false
};
this.tasks.unshift(newTask);
this.stats.total++;
this.stats.toDo++;
this.hideAIModal();
this.showToast(`Task "${name}" created successfully!`, 'success');
this.updateUI();
this.renderTasks();
} catch (error) {
this.showToast('Failed to create task: ' + error.message, 'error');
}
}
async updateTaskStatus(taskId, newStatus) {
try {
const task = this.tasks.find(t => t.id === taskId);
if (task) {
const oldStatus = task.status;
task.status = newStatus;
if (newStatus === 'Done') {
task.progress = 100;
} else if (newStatus === 'In Progress' && task.progress === 0) {
task.progress = 25;
}
// Update stats
if (oldStatus === 'To Do') this.stats.toDo--;
else if (oldStatus === 'In Progress') this.stats.inProgress--;
else if (oldStatus === 'Done') this.stats.completed--;
if (newStatus === 'To Do') this.stats.toDo++;
else if (newStatus === 'In Progress') this.stats.inProgress++;
else if (newStatus === 'Done') this.stats.completed++;
this.hideAIModal();
this.showToast(`Task status updated to ${newStatus}`, 'success');
this.updateUI();
this.renderTasks();
}
} catch (error) {
this.showToast('Failed to update task: ' + error.message, 'error');
}
}
prioritizeTasks() {
this.updateTaskStats();
this.showToast('🎯 Tasks automatically prioritized by AI algorithm!', 'success');
// Sort tasks by priority and overdue status
this.tasks.sort((a, b) => {
if (a.isOverdue && !b.isOverdue) return -1;
if (!a.isOverdue && b.isOverdue) return 1;
const priorityOrder = { 'High': 0, 'Medium': 1, 'Low': 2 };
return (priorityOrder[a.priority] || 2) - (priorityOrder[b.priority] || 2);
});
this.renderTasks();
}
bulkUpdate() {
this.updateTaskStats();
this.showToast('📝 Bulk update feature coming soon!', 'info');
}
generateReport() {
const completionRate = this.stats.total > 0 ? Math.round((this.stats.completed / this.stats.total) * 100) : 0;
this.showAIModal(`
📊 Progress Report
${this.stats.total}
Total Tasks
${completionRate}%
Completion Rate
Task Breakdown
Completed:
${this.stats.completed}
In Progress:
${this.stats.inProgress}
To Do:
${this.stats.toDo}
Overdue:
${this.stats.overdue}
💡 AI Insights
- • Your completion rate is ${completionRate > 70 ? 'excellent' : completionRate > 50 ? 'good' : 'needs improvement'}
- • ${this.stats.overdue > 0 ? `Focus on ${this.stats.overdue} overdue tasks first` : 'Great job staying on top of deadlines!'}
- • Consider breaking down large tasks into smaller chunks
`);
}
// Search and filter functions
async handleSearch() {
const searchInput = document.getElementById('taskSearchInput');
if (searchInput) {
await this.searchTasks(searchInput.value);
}
}
async handleFilter(status) {
await this.filterTasks(status);
// Update filter button states
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('bg-orange-200', 'text-orange-800');
btn.classList.add('bg-gray-100', 'text-gray-700');
});
const activeBtn = document.querySelector(`[data-status="${status}"]`);
if (activeBtn) {
activeBtn.classList.remove('bg-gray-100', 'text-gray-700');
activeBtn.classList.add('bg-orange-200', 'text-orange-800');
}
}
}
// Initialize Task Agent when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
console.log('Initializing Task Agent...');
window.taskAgent = new TaskAgent();
// Make functions globally available for onclick handlers
window.executeTaskCommand = () => taskAgent.executeTaskCommand();
window.setTaskCommand = (cmd) => taskAgent.setTaskCommand(cmd);
window.createTask = () => taskAgent.createTask();
window.prioritizeTasks = () => taskAgent.prioritizeTasks();
window.bulkUpdate = () => taskAgent.bulkUpdate();
window.generateReport = () => taskAgent.generateReport();
window.closeAIModal = () => taskAgent.hideAIModal();
console.log('✅ Task Agent initialized successfully');
});
// Global helper functions
function goHome() {
window.location.href = 'index.html';
}
console.log('✅ Task Agent JS loaded successfully');