/** * Tasks Widget - displays task summary and list */ import { useState, useEffect } from "react"; import { CheckCircle, Circle, Clock, AlertCircle } from "lucide-react"; import { TaskPriority, TaskStatus, type WidgetProps, type Task } from "@mosaic/shared"; import { fetchTasks } from "@/lib/api/tasks"; export function TasksWidget({ id: _id, config: _config }: WidgetProps): React.JSX.Element { const [tasks, setTasks] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { let isMounted = true; const loadTasks = async (): Promise => { setIsLoading(true); try { const data = await fetchTasks(); if (isMounted) { setTasks(data); } } catch { if (isMounted) { setTasks([]); } } finally { if (isMounted) { setIsLoading(false); } } }; void loadTasks(); return (): void => { isMounted = false; }; }, []); const getPriorityIcon = (priority: TaskPriority): React.JSX.Element => { switch (priority) { case TaskPriority.HIGH: return ; case TaskPriority.MEDIUM: return ; case TaskPriority.LOW: return ; default: return ; } }; const getStatusIcon = (status: TaskStatus): React.JSX.Element => { return status === TaskStatus.COMPLETED ? ( ) : ( ); }; const stats = { total: tasks.length, inProgress: tasks.filter((t) => t.status === TaskStatus.IN_PROGRESS).length, completed: tasks.filter((t) => t.status === TaskStatus.COMPLETED).length, }; if (isLoading) { return (
Loading tasks...
); } return (
{/* Summary stats */}
{stats.total}
Total
{stats.inProgress}
In Progress
{stats.completed}
Done
{/* Task list */}
{tasks.length === 0 ? (
No tasks yet
) : ( tasks.slice(0, 5).map((task) => (
{getStatusIcon(task.status)}
{task.title}
{task.dueDate && (
Due: {new Date(task.dueDate).toLocaleDateString()}
)}
{getPriorityIcon(task.priority)}
)) )}
); }