/** * TaskListWidget - Unified Task Management * Integrates Todoist, Asana, TickTick, Notion tasks * * Features: * - Auto-discovery of task sources * - Priority sorting * - Quick add * - Broadcasting task events */ import React, { useState, useEffect } from 'react'; import { CheckSquare, Square, Plus, Flag, Calendar as CalIcon, Trash2 } from 'lucide-react'; import { useLiveData } from '@/hooks/useLiveData'; import { useWidgetCommunication } from '@/contexts/WidgetContext'; import { cn } from '@/lib/utils'; interface Task { id: string; title: string; completed: boolean; priority: 1 | 2 | 3 | 4; dueDate?: string; project?: string; source: string; } interface TaskListWidgetProps { widgetId: string; } export default function TaskListWidget({ widgetId }: TaskListWidgetProps) { const [filter, setFilter] = useState<'all' | 'today' | 'high-priority'>('today'); const [newTaskTitle, setNewTaskTitle] = useState(''); // AUTO-DISCOVERY const { data: taskData, connected, recommendedSources, refetch, } = useLiveData({ widgetId, widgetType: 'tasks', requiredSources: ['todoist', 'asana'], optionalSources: ['ticktick', 'notion-tasks'], autoConnect: true, pollInterval: 30000, }); // INTER-WIDGET COMMUNICATION const { broadcastEvent, subscribeToEvent } = useWidgetCommunication(widgetId); // Broadcast task completion const handleToggleTask = async (task: Task) => { // TODO: API call to toggle task broadcastEvent({ type: task.completed ? 'task.uncompleted' : 'task.completed', data: { taskId: task.id, title: task.title, source: task.source, }, }); refetch(); }; // Listen for calendar events to create tasks useEffect(() => { const unsub = subscribeToEvent('calendar.meeting.upcoming', (event) => { // Auto-create prep task for upcoming meetings const meetingTitle = event.data.title; // TODO: Create task "Prepare for: {meetingTitle}" }); return () => unsub(); }, []); const handleAddTask = async () => { if (!newTaskTitle.trim()) return; // TODO: API call to create task broadcastEvent({ type: 'task.created', data: { title: newTaskTitle, }, }); setNewTaskTitle(''); refetch(); }; const tasks: Task[] = taskData?.tasks || []; const filteredTasks = tasks.filter(task => { if (filter === 'today') { if (!task.dueDate) return false; return new Date(task.dueDate).toDateString() === new Date().toDateString(); } if (filter === 'high-priority') { return task.priority === 1 || task.priority === 2; } return true; }); const getPriorityColor = (priority: number) => { switch (priority) { case 1: return 'text-red-400'; case 2: return 'text-orange-400'; case 3: return 'text-yellow-400'; default: return 'text-gray-400'; } }; return (
{/* Header */}
Tasks
{filteredTasks.filter(t => !t.completed).length} active
{/* Filters */}
{(['all', 'today', 'high-priority'] as const).map((f) => ( ))}
{/* Quick Add */}
setNewTaskTitle(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleAddTask()} placeholder="Add a task..." className="flex-1 px-3 py-2 bg-white/5 border border-emerald-500/30 rounded text-sm text-white placeholder-emerald-300/50 focus:outline-none focus:border-emerald-500" />
{/* Task List */}
{filteredTasks.length === 0 && (

No tasks for this filter

)} {filteredTasks.map((task) => (
{/* Checkbox */} {/* Task Content */}
{task.title}
{/* Priority */}
P{task.priority}
{/* Due Date */} {task.dueDate && (
{new Date(task.dueDate).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
)} {/* Project */} {task.project && ( @ {task.project} )} {/* Source */} {task.source}
{/* Delete (on hover) */}
))}
{/* Source Recommendations */} {recommendedSources.length > 0 && (
Missing Task Sources:
{recommendedSources.map((source) => (
{source.name}
))}
)} {/* Stats Footer */}
{tasks.filter(t => !t.completed).length}
Active
{tasks.filter(t => t.completed).length}
Done
{tasks.filter(t => !t.completed && t.priority <= 2).length}
High Pri
); }