import { useState, useEffect, useCallback } from 'react' import { Link } from 'react-router-dom' import { useSources, TodoTask } from '@/hooks/useSources' import './TodoWidget.css' const PRIORITY_ORDER = { urgent: 0, high: 1, medium: 2, low: 3 } const PRIORITY_COLORS = { urgent: '#dc2626', high: '#ea580c', medium: '#ca8a04', low: '#16a34a', } interface TodoWidgetProps { maxItems?: number } const TodoWidget = ({ maxItems = 5 }: TodoWidgetProps) => { const { listTasks, completeTask, createTask } = useSources() const [tasks, setTasks] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [newTaskTitle, setNewTaskTitle] = useState('') const [isAdding, setIsAdding] = useState(false) const loadTasks = useCallback(async () => { try { const data = await listTasks({ limit: maxItems + 5 }) // Sort by priority then due date const sorted = [...data].sort((a, b) => { // Priority first const aPriority = a.priority ? PRIORITY_ORDER[a.priority] : 4 const bPriority = b.priority ? PRIORITY_ORDER[b.priority] : 4 if (aPriority !== bPriority) return aPriority - bPriority // Then by due date if (a.due_date && b.due_date) { return new Date(a.due_date).getTime() - new Date(b.due_date).getTime() } if (a.due_date) return -1 if (b.due_date) return 1 return 0 }) setTasks(sorted.slice(0, maxItems)) setError(null) } catch (e) { setError(e instanceof Error ? e.message : 'Failed to load tasks') } finally { setLoading(false) } }, [listTasks, maxItems]) useEffect(() => { loadTasks() }, [loadTasks]) const handleComplete = async (taskId: number) => { try { await completeTask(taskId) // Remove from list setTasks(prev => prev.filter(t => t.id !== taskId)) // Reload to get next task if available loadTasks() } catch (e) { console.error('Failed to complete task:', e) } } const handleAddTask = async (e: React.FormEvent) => { e.preventDefault() if (!newTaskTitle.trim()) return setIsAdding(true) try { await createTask({ task_title: newTaskTitle.trim() }) setNewTaskTitle('') loadTasks() } catch (e) { console.error('Failed to create task:', e) } finally { setIsAdding(false) } } const formatDueDate = (dueDate: string) => { const date = new Date(dueDate) const today = new Date() today.setHours(0, 0, 0, 0) const tomorrow = new Date(today) tomorrow.setDate(tomorrow.getDate() + 1) const taskDate = new Date(date) taskDate.setHours(0, 0, 0, 0) if (taskDate.getTime() < today.getTime()) { return { text: 'Overdue', className: 'overdue' } } if (taskDate.getTime() === today.getTime()) { return { text: 'Today', className: 'today' } } if (taskDate.getTime() === tomorrow.getTime()) { return { text: 'Tomorrow', className: 'tomorrow' } } return { text: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }), className: '' } } if (loading) { return (

Tasks

Loading...
) } if (error) { return (

Tasks

{error}
) } return (

Tasks

{tasks.length}
setNewTaskTitle(e.target.value)} disabled={isAdding} className="todo-add-input" />
{tasks.length === 0 ? (
No pending tasks
) : (
    {tasks.map(task => (
  • {task.task_title}
    {task.priority && ( {task.priority} )} {task.due_date && ( {formatDueDate(task.due_date).text} )}
  • ))}
)}
View all tasks
) } export default TodoWidget