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",