import React, { useState, useEffect, useContext, useCallback } from "react"; import axios from "axios"; import { toast } from "react-toastify"; import { AuthContext } from "../context/AuthContext"; import { SocketContext } from "../context/SocketContext"; /** * TaskList component displays maintenance tasks and allows task completion * Includes real-time updates via Socket.IO */ const TaskList = () => { const { auth } = useContext(AuthContext); const { socket, connected, on, off } = useContext(SocketContext); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [completingTaskId, setCompletingTaskId] = useState(null); // Load tasks from API const loadTasks = useCallback(async () => { try { setLoading(true); setError(null); const res = await axios.get("/api/tasks"); setTasks(res.data); } catch (err) { console.error("Error loading tasks:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to load tasks. Please try again later."; setError(errorMessage); toast.error(errorMessage); } finally { setLoading(false); } }, []); useEffect(() => { loadTasks(); }, [loadTasks]); // Handle real-time task updates via Socket.IO useEffect(() => { if (!socket || !connected) return; const handleTaskUpdate = (data) => { console.log("Received task update:", data); if (data.type === "task_completed") { // Update specific task status setTasks((prevTasks) => prevTasks.map((task) => task._id === data.taskId ? { ...task, status: "completed" } : task ) ); toast.success("Task completed!"); } else if (data.type === "new_task") { // Add new task to the list setTasks((prevTasks) => [data.task, ...prevTasks]); toast.info("New task available!"); } else if (data.type === "task_updated") { // Update existing task setTasks((prevTasks) => prevTasks.map((task) => task._id === data.task._id ? data.task : task ) ); } else if (data.type === "task_deleted") { // Remove deleted task setTasks((prevTasks) => prevTasks.filter((task) => task._id !== data.taskId) ); } }; // Subscribe to task updates on("taskUpdate", handleTaskUpdate); // Cleanup on unmount return () => { off("taskUpdate", handleTaskUpdate); }; }, [socket, connected, on, off]); // Complete a task const completeTask = async (id) => { if (!auth.isAuthenticated) { toast.warning("Please login to complete tasks"); return; } try { setCompletingTaskId(id); const token = localStorage.getItem("token"); const res = await axios.put( `/api/tasks/${id}`, {}, { headers: { "x-auth-token": token, }, } ); setTasks(tasks.map((task) => (task._id === id ? res.data : task))); toast.success("Task completed successfully!"); } catch (err) { console.error("Error completing task:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to complete task. Please try again."; toast.error(errorMessage); } finally { setCompletingTaskId(null); } }; if (loading) { return (
Loading tasks...
{error}