import { useState, useEffect, useCallback } from 'react'; interface Task { id: number; title: string; description: string; completed: boolean; created_at?: string; updated_at?: string; } export default function TaskManager() { const [tasks, setTasks] = useState([]); const [newTask, setNewTask] = useState({ title: '', description: '' }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchTasks = useCallback(async () => { try { setError(null); const response = await fetch('/api/tasks'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('Fetched tasks:', data); setTasks(Array.isArray(data) ? data : []); } catch (error) { console.error('Failed to fetch tasks:', error); setError(error instanceof Error ? error.message : 'Failed to fetch tasks'); setTasks([]); } finally { setLoading(false); } }, []); useEffect(() => { fetchTasks(); }, [fetchTasks]); const createTask = async (e: React.FormEvent) => { e.preventDefault(); if (!newTask.title.trim()) return; try { const response = await fetch('/api/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newTask) }); if (response.ok) { setNewTask({ title: '', description: '' }); fetchTasks(); } } catch (error) { console.error('Failed to create task:', error); } }; const toggleTask = async (task: Task) => { try { await fetch(`/api/tasks/${task.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...task, completed: !task.completed }) }); fetchTasks(); } catch (error) { console.error('Failed to update task:', error); } }; const deleteTask = async (id: number) => { try { await fetch(`/api/tasks/${id}`, { method: 'DELETE' }); fetchTasks(); } catch (error) { console.error('Failed to delete task:', error); } }; if (loading) { return (

Task Manager

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

Task Manager

Error: {error}

); } return (

Task Manager

setNewTask({ ...newTask, title: e.target.value })} className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" />