The job detail page was only server-rendered with no live updates, unlike the jobs list page. Add a lightweight JobDetailLive client component that subscribes to the existing SSE endpoint and calls router.refresh() on each update, keeping the page in sync while a job is running. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
45 lines
989 B
TypeScript
45 lines
989 B
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
interface JobDetailLiveProps {
|
|
jobId: string;
|
|
isTerminal: boolean;
|
|
}
|
|
|
|
export function JobDetailLive({ jobId, isTerminal }: JobDetailLiveProps) {
|
|
const router = useRouter();
|
|
const isTerminalRef = useRef(isTerminal);
|
|
isTerminalRef.current = isTerminal;
|
|
|
|
useEffect(() => {
|
|
if (isTerminalRef.current) return;
|
|
|
|
const eventSource = new EventSource(`/api/jobs/${jobId}/stream`);
|
|
|
|
eventSource.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
router.refresh();
|
|
|
|
if (data.status === "success" || data.status === "failed" || data.status === "cancelled") {
|
|
eventSource.close();
|
|
}
|
|
} catch {
|
|
// ignore parse errors
|
|
}
|
|
};
|
|
|
|
eventSource.onerror = () => {
|
|
eventSource.close();
|
|
};
|
|
|
|
return () => {
|
|
eventSource.close();
|
|
};
|
|
}, [jobId, router]);
|
|
|
|
return null;
|
|
}
|