diff --git a/apps/backoffice/app/components/JobRow.tsx b/apps/backoffice/app/components/JobRow.tsx index b2c6a0e..87cb2b8 100644 --- a/apps/backoffice/app/components/JobRow.tsx +++ b/apps/backoffice/app/components/JobRow.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import Link from "next/link"; import { useTranslation } from "../../lib/i18n/context"; import { JobProgress } from "./JobProgress"; -import { StatusBadge, JobTypeBadge, Button, MiniProgressBar, Icon } from "./ui"; +import { StatusBadge, JobTypeBadge, Button, MiniProgressBar, Icon, Tooltip } from "./ui"; interface JobRowProps { job: { @@ -21,6 +21,7 @@ interface JobRowProps { indexed_files: number; removed_files: number; errors: number; + refreshed?: number; } | null; progress_percent: number | null; processed_files: number | null; @@ -117,49 +118,74 @@ export function JobRow({ job, libraryName, highlighted, onCancel, formatDate, fo
{/* Files: indexed count */} {indexed > 0 && ( - - - {indexed} - + + + + {indexed} + + )} {/* Removed files */} {removed > 0 && ( - - - {removed} - + + + + {removed} + + )} {/* Thumbnails */} {hasThumbnailPhase && job.total_files != null && job.total_files > 0 && ( - - - {job.total_files} - + + + + {job.total_files} + + )} {/* Metadata batch: series processed */} {isMetadataBatch && job.total_files != null && job.total_files > 0 && ( - - - {job.total_files} - + + + + {job.total_files} + + )} - {/* Metadata refresh: links refreshed */} + {/* Metadata refresh: total links + refreshed count */} {isMetadataRefresh && job.total_files != null && job.total_files > 0 && ( - - - {job.total_files} - + + + + {job.total_files} + + + )} + {isMetadataRefresh && job.stats_json?.refreshed != null && job.stats_json.refreshed > 0 && ( + + + + {job.stats_json.refreshed} + + )} {/* Errors */} {errors > 0 && ( - - - {errors} - + + + + {errors} + + )} {/* Scanned only (no other stats) */} {indexed === 0 && removed === 0 && errors === 0 && !hasThumbnailPhase && !isMetadataBatch && !isMetadataRefresh && scanned > 0 && ( - {t("jobRow.scanned", { count: scanned })} + + + + {scanned} + + )} {/* Nothing to show */} {indexed === 0 && removed === 0 && errors === 0 && scanned === 0 && !hasThumbnailPhase && !isMetadataBatch && !isMetadataRefresh && ( diff --git a/apps/backoffice/app/components/JobsList.tsx b/apps/backoffice/app/components/JobsList.tsx index 4971351..6a29ea3 100644 --- a/apps/backoffice/app/components/JobsList.tsx +++ b/apps/backoffice/app/components/JobsList.tsx @@ -18,6 +18,7 @@ interface Job { indexed_files: number; removed_files: number; errors: number; + refreshed?: number; } | null; progress_percent: number | null; processed_files: number | null; diff --git a/apps/backoffice/app/components/ui/StatBox.tsx b/apps/backoffice/app/components/ui/StatBox.tsx index 76f98ca..821aadf 100644 --- a/apps/backoffice/app/components/ui/StatBox.tsx +++ b/apps/backoffice/app/components/ui/StatBox.tsx @@ -4,6 +4,7 @@ interface StatBoxProps { value: ReactNode; label: string; variant?: "default" | "primary" | "success" | "warning" | "error"; + icon?: ReactNode; className?: string; } @@ -23,10 +24,13 @@ const valueVariantStyles: Record = { error: "text-destructive", }; -export function StatBox({ value, label, variant = "default", className = "" }: StatBoxProps) { +export function StatBox({ value, label, variant = "default", icon, className = "" }: StatBoxProps) { return (
- {value} +
+ {icon && {icon}} + {value} +
{label}
); diff --git a/apps/backoffice/app/components/ui/Tooltip.tsx b/apps/backoffice/app/components/ui/Tooltip.tsx new file mode 100644 index 0000000..0b7173f --- /dev/null +++ b/apps/backoffice/app/components/ui/Tooltip.tsx @@ -0,0 +1,18 @@ +import { ReactNode } from "react"; + +interface TooltipProps { + label: string; + children: ReactNode; + className?: string; +} + +export function Tooltip({ label, children, className = "" }: TooltipProps) { + return ( + + {children} + + {label} + + + ); +} diff --git a/apps/backoffice/app/components/ui/index.ts b/apps/backoffice/app/components/ui/index.ts index 3c0c0af..00d7d5e 100644 --- a/apps/backoffice/app/components/ui/index.ts +++ b/apps/backoffice/app/components/ui/index.ts @@ -19,3 +19,4 @@ export { } from "./Form"; export { PageIcon, NavIcon, Icon } from "./Icon"; export { CursorPagination, OffsetPagination } from "./Pagination"; +export { Tooltip } from "./Tooltip"; diff --git a/apps/backoffice/app/jobs/[id]/page.tsx b/apps/backoffice/app/jobs/[id]/page.tsx index 80e7c08..66f999c 100644 --- a/apps/backoffice/app/jobs/[id]/page.tsx +++ b/apps/backoffice/app/jobs/[id]/page.tsx @@ -587,7 +587,16 @@ export default async function JobDetailPage({ params }: JobDetailPageProps) {
- + + + + } + /> 0 ? "error" : "default"} /> diff --git a/apps/backoffice/lib/api.ts b/apps/backoffice/lib/api.ts index 78b9429..41a2ad9 100644 --- a/apps/backoffice/lib/api.ts +++ b/apps/backoffice/lib/api.ts @@ -32,6 +32,7 @@ export type IndexJobDto = { removed_files: number; errors: number; warnings: number; + refreshed?: number; } | null; progress_percent: number | null; processed_files: number | null; diff --git a/apps/backoffice/lib/i18n/en.ts b/apps/backoffice/lib/i18n/en.ts index 5f92568..24fd73a 100644 --- a/apps/backoffice/lib/i18n/en.ts +++ b/apps/backoffice/lib/i18n/en.ts @@ -258,6 +258,7 @@ const en: Record = { "jobRow.thumbnailsGenerated": "{{count}} thumbnails generated", "jobRow.metadataProcessed": "{{count}} series processed", "jobRow.metadataRefreshed": "{{count}} series refreshed", + "jobRow.metadataLinks": "{{count}} links analyzed", "jobRow.errors": "{{count}} errors", "jobRow.view": "View", diff --git a/apps/backoffice/lib/i18n/fr.ts b/apps/backoffice/lib/i18n/fr.ts index efcc78e..4ba7c23 100644 --- a/apps/backoffice/lib/i18n/fr.ts +++ b/apps/backoffice/lib/i18n/fr.ts @@ -256,6 +256,7 @@ const fr = { "jobRow.thumbnailsGenerated": "{{count}} miniatures générées", "jobRow.metadataProcessed": "{{count}} séries traitées", "jobRow.metadataRefreshed": "{{count}} séries rafraîchies", + "jobRow.metadataLinks": "{{count}} liens analysés", "jobRow.errors": "{{count}} erreurs", "jobRow.view": "Voir",