);
}
// Hiển thị tiến độ + log + danh sách item của một job đang chạy.
export function JobView({ job }) {
if (!job) return null;
const pct = Math.round((job.progress || 0) * 100);
return (
);
}
// Lớp phủ "ĐANG XỬ LÝ": hiện NGAY khi busy=true (kể cả trước khi có job), phủ kín
// màn hình -> chặn mọi thao tác cho tới khi xong. Có spinner + tiến độ + bước hiện tại.
export function ProcessingOverlay({ busy, job, title = "Đang xử lý…" }) {
if (!busy) return null;
const pct = Math.round((job?.progress || 0) * 100);
const items = job?.items || [];
const running = items.find((i) => i.status === "running");
const doneCount = items.filter((i) => i.status === "done").length;
const lastLog = job?.logs?.length ? job.logs[job.logs.length - 1].msg : "";
// Đang xếp hàng chờ tài nguyên máy chủ (nhiều người dùng cùng lúc).
const queued = job?.status === "queued" && (job?.queue_total || 0) > 0;
const queueMsg = queued
? `Đang xếp hàng — vị trí ${(job.queue_pos || 0) + 1}/${job.queue_total}. Máy chủ đang bận, job của bạn sẽ tự chạy khi tới lượt.`
: "";
const sub = queueMsg || running?.detail || lastLog || "Đang xử lý trên máy chủ, vui lòng đợi…";
return (
Thao tác bị khoá tới khi xử lý xong — đừng đóng tab.
);
}
// Thông báo cho user biết dữ liệu được giữ tạm theo phiên (cache), không lưu lâu dài.
export function CacheNote({ onClose }) {
return (
Dữ liệu được lưu tạm theo phiên làm việc (cache trên trình duyệt + vùng tạm trên máy chủ),
giúp bạn chuyển qua lại giữa các tool mà không mất tiến trình. Sau khi xử lý xong, hãy
tải kết quả về máy — dữ liệu tạm sẽ tự xoá, không lưu trữ lâu dài.
{onClose && }