"use client"; import { useState } from "react"; import Link from "next/link"; import { JobProgress } from "./JobProgress"; import { StatusBadge, JobTypeBadge, Button, MiniProgressBar } from "./ui"; interface JobRowProps { job: { id: string; library_id: string | null; type: string; status: string; created_at: string; started_at: string | null; finished_at: string | null; error_opt: string | null; stats_json: { scanned_files: number; indexed_files: number; removed_files: number; errors: number; } | null; progress_percent: number | null; processed_files: number | null; total_files: number | null; }; libraryName: string | undefined; highlighted?: boolean; onCancel: (id: string) => void; formatDate: (date: string) => string; formatDuration: (start: string, end: string | null) => string; } export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, formatDuration }: JobRowProps) { const isActive = job.status === "running" || job.status === "pending" || job.status === "generating_thumbnails"; const [showProgress, setShowProgress] = useState(highlighted || isActive); const handleComplete = () => { setShowProgress(false); window.location.reload(); }; // Calculate duration const duration = job.started_at ? formatDuration(job.started_at, job.finished_at) : "-"; // Get file stats const scanned = job.stats_json?.scanned_files ?? 0; const indexed = job.stats_json?.indexed_files ?? 0; const removed = job.stats_json?.removed_files ?? 0; const errors = job.stats_json?.errors ?? 0; const isThumbnailPhase = job.status === "generating_thumbnails"; const isThumbnailJob = job.type === "thumbnail_rebuild" || job.type === "thumbnail_regenerate"; const hasThumbnailPhase = isThumbnailPhase || isThumbnailJob; // Files column: index-phase stats only const filesDisplay = job.status === "running" && !isThumbnailPhase ? job.total_files != null ? `${job.processed_files ?? 0}/${job.total_files}` : scanned > 0 ? `${scanned} scanned` : "-" : job.status === "success" && (indexed > 0 || removed > 0 || errors > 0) ? null // rendered below as ✓ / − / ⚠ : scanned > 0 ? `${scanned} scanned` : "—"; // Thumbnails column const thumbInProgress = hasThumbnailPhase && (job.status === "running" || isThumbnailPhase); const thumbDisplay = thumbInProgress && job.total_files != null ? `${job.processed_files ?? 0}/${job.total_files}` : job.status === "success" && job.total_files != null && hasThumbnailPhase ? `✓ ${job.total_files}` : "—"; return ( <> {job.id.slice(0, 8)} {job.library_id ? libraryName || job.library_id.slice(0, 8) : "—"}
{job.error_opt && ( ! )} {isActive && ( )}
{filesDisplay !== null ? ( {filesDisplay} ) : (
✓ {indexed} {removed > 0 && − {removed}} {errors > 0 && ⚠ {errors}}
)} {job.status === "running" && !isThumbnailPhase && job.total_files != null && ( )}
{thumbDisplay} {thumbInProgress && job.total_files != null && ( )}
{duration} {formatDate(job.created_at)}
View {(job.status === "pending" || job.status === "running" || job.status === "generating_thumbnails") && ( )}
{showProgress && isActive && ( )} ); }