import { useEffect, useState } from "react"; import { Link, Outlet, useOutletContext } from "@remix-run/react/dist"; import { useSocket } from "../context"; import { L33tTask } from "l33t-lib"; import { L33tMemDB } from "l33t-lib"; import TimedStatus from "../components/TimedStatus"; type ContextType = { toggleSelection: (id: string) => void; selectedIds: string[]; memoryDB: L33tMemDB; }; interface HTMLRendererProps { html: string; className?: string; } const HTMLRenderer: React.FC = ({ html, className = "" }) => (
); interface ErrorDisplayProps { error: string; } const ErrorDisplay: React.FC = ({ error }) => (
Error

{error}

); export default function Tasks() { const { memoryDB, toggleSelection, selectedIds } = useOutletContext(); const [tasks, setTasks] = useState>({}); const socket = useSocket(); useEffect(() => { if (!socket) return; const handleL33tUpdate = (obj: { key: string; task: L33tTask }) => { setTasks(prev => ({ ...prev, [obj.key]: obj.task })); }; const handleTaskUpdate = (taskId: string, task: L33tTask | null) => { setTasks(prev => { if (task === null) { const newTasks = { ...prev }; delete newTasks[taskId]; return newTasks; } return { ...prev, [taskId]: task }; }); }; socket.on("l33t_task_exec", handleL33tUpdate); socket.on("l33t_task_update", handleTaskUpdate); socket.on("l33t_delete_task_result", result => { if (!result.success) console.error("Delete failed:", result.error); }); return () => { socket.off("l33t_task_exec", handleL33tUpdate); socket.off("l33t_task_update", handleTaskUpdate); socket.off("l33t_delete_task_result"); }; }, [socket]); useEffect(() => { if (memoryDB) setTasks(memoryDB.tasks || {}); }, [memoryDB]); const addTask = async () => { if (!socket) return; const newId = `stream_${Date.now()}`; const task = new L33tTask(); socket.emit("l33t_add_task", newId, task); }; return (

Tasks

{Object.entries(tasks).map(([taskId, task]) => { if (!task) return null; return (

{taskId}

Output {task.error ? ( ) : ( )}
); })}
); }