// app/tasks/TaskDetail.tsx // Expanded panel for a single task. Shows log, result, error. Has // retry, cancel, and delete buttons. "use client"; import { useState } from "react"; import { TASK_TYPE_META, STATUS_LABEL, PRIORITY_LABEL } from "./columns"; import { type Task, retryTask, cancelTask, deleteTask } from "./api"; interface TaskDetailProps { task: Task; onClose: () => void; onMutated: () => void; onToast: (kind: "info" | "success" | "error" | "warn", title: string, body?: string) => void; } export default function TaskDetail({ task, onClose, onMutated, onToast }: TaskDetailProps) { const [busy, setBusy] = useState(null); const meta = TASK_TYPE_META[task.task_type]; async function act(label: string, fn: () => Promise) { setBusy(label); try { await fn(); onMutated(); onToast("success", `${label} done`); } catch (err: any) { onToast("error", `${label} failed`, err.message); } finally { setBusy(null); } } return (
e.stopPropagation()} >
{meta.icon} {meta.label} {STATUS_LABEL[task.status]} {PRIORITY_LABEL[task.priority]} {task.retry_count > 0 ? ( retry ×{task.retry_count} ) : null}

{task.title}

{task.description ? (

{task.description}

) : null}
{task.payload && Object.keys(task.payload as object).length > 0 ? (
                {JSON.stringify(task.payload, null, 2)}
              
) : null} {task.error ? (

{task.error}

) : null} {task.log && task.log.length > 0 ? (
                {task.log.join("\n")}
              
) : null} {task.result ? (
                {JSON.stringify(task.result, null, 2)}
              
) : null}
{(task.status === "failed" || task.status === "done") && ( )} {task.status === "in_progress" && ( )}
); } function Meta({ label, value }: { label: string; value: string }) { return (

{label}

{value}

); } function Section({ title, children }: { title: string; children: React.ReactNode }) { return (

{title}

{children}
); } function formatTime(iso: string | null): string { if (!iso) return "—"; const t = new Date(iso.includes("T") ? iso : iso.replace(" ", "T") + "Z"); if (isNaN(t.getTime())) return "—"; return t.toLocaleString(); }