import { Card, CardHeader, CardTitle, CardContent } from "@/app/components/ui"; import type { TranslateFunction } from "@/lib/i18n/dictionaries"; interface JobTimelineCardProps { job: { type: string; status: string; created_at: string; started_at: string | null; finished_at: string | null; phase2_started_at: string | null; generating_thumbnails_started_at: string | null; stats_json: { scanned_files: number; indexed_files: number; removed_files: number; warnings: number; } | null; total_files: number | null; processed_files: number | null; }; isThumbnailOnly: boolean; t: TranslateFunction; locale: string; formatDuration: (start: string, end: string | null) => string; } export function JobTimelineCard({ job, isThumbnailOnly, t, locale, formatDuration }: JobTimelineCardProps) { const isCompleted = job.status === "success"; const isFailed = job.status === "failed"; const isExtractingPages = job.status === "extracting_pages"; const isThumbnailPhase = job.status === "generating_thumbnails"; return ( {t("jobDetail.timeline")}
{/* Created */}
{t("jobDetail.created")}

{new Date(job.created_at).toLocaleString(locale)}

{/* Phase 1 start */} {job.started_at && job.phase2_started_at && (
{t("jobDetail.phase1")}

{new Date(job.started_at).toLocaleString(locale)}

{t("jobDetail.duration", { duration: formatDuration(job.started_at, job.phase2_started_at) })} {job.stats_json && ( · {job.stats_json.scanned_files} {t("jobDetail.scanned").toLowerCase()}, {job.stats_json.indexed_files} {t("jobDetail.indexed").toLowerCase()} {job.stats_json.removed_files > 0 && `, ${job.stats_json.removed_files} ${t("jobDetail.removed").toLowerCase()}`} {(job.stats_json.warnings ?? 0) > 0 && `, ${job.stats_json.warnings} ${t("jobDetail.warnings").toLowerCase()}`} )}

)} {/* Phase 2a — Extracting pages */} {job.phase2_started_at && !isThumbnailOnly && (
{t("jobDetail.phase2a")}

{new Date(job.phase2_started_at).toLocaleString(locale)}

{t("jobDetail.duration", { duration: formatDuration(job.phase2_started_at, job.generating_thumbnails_started_at ?? job.finished_at ?? null) })} {!job.generating_thumbnails_started_at && !job.finished_at && isExtractingPages && ( · {t("jobDetail.inProgress")} )}

)} {/* Phase 2b — Generating thumbnails */} {(job.generating_thumbnails_started_at || (job.phase2_started_at && isThumbnailOnly)) && (
{isThumbnailOnly ? t("jobType.thumbnail_rebuild") : t("jobDetail.phase2b")}

{(job.generating_thumbnails_started_at ? new Date(job.generating_thumbnails_started_at) : job.phase2_started_at ? new Date(job.phase2_started_at) : null)?.toLocaleString(locale)}

{(job.generating_thumbnails_started_at || job.finished_at) && (

{t("jobDetail.duration", { duration: formatDuration( job.generating_thumbnails_started_at ?? job.phase2_started_at!, job.finished_at ?? null ) })} {job.total_files != null && job.total_files > 0 && ( · {job.processed_files ?? job.total_files} {t("jobType.thumbnail_rebuild").toLowerCase()} )}

)} {!job.finished_at && isThumbnailPhase && ( {t("jobDetail.inProgress")} )}
)} {/* Started — for jobs without phase2 */} {job.started_at && !job.phase2_started_at && (
{t("jobDetail.started")}

{new Date(job.started_at).toLocaleString(locale)}

)} {/* Pending */} {!job.started_at && (
{t("jobDetail.pendingStart")}
)} {/* Finished */} {job.finished_at && (
{isCompleted ? t("jobDetail.finished") : isFailed ? t("jobDetail.failed") : t("jobDetail.cancelled")}

{new Date(job.finished_at).toLocaleString(locale)}

)}
); }