feat: add batch metadata jobs, series filters, and translate backoffice to French

- Add metadata_batch job type with background processing via tokio::spawn
- Auto-apply metadata only when single result at 100% confidence
- Support primary + fallback provider per library, "none" to opt out
- Add batch report/results API endpoints and job detail UI
- Add series_status and has_missing filters to both series listing pages
- Add GET /series/statuses endpoint for dynamic filter options
- Normalize series_metadata status values (migration 0036)
- Hide ComicVine provider tab when no API key configured
- Translate entire backoffice UI from English to French

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 18:26:44 +01:00
parent 9a8c1577af
commit b955c2697c
46 changed files with 2161 additions and 379 deletions

View File

@@ -11,7 +11,7 @@ import { MobileNav } from "./components/MobileNav";
export const metadata: Metadata = {
title: "StripStream Backoffice",
description: "Backoffice administration for StripStream Librarian"
description: "Administration backoffice pour StripStream Librarian"
};
type NavItem = {
@@ -21,17 +21,17 @@ type NavItem = {
};
const navItems: NavItem[] = [
{ href: "/", label: "Dashboard", icon: "dashboard" },
{ href: "/books", label: "Books", icon: "books" },
{ href: "/series", label: "Series", icon: "series" },
{ href: "/libraries", label: "Libraries", icon: "libraries" },
{ href: "/jobs", label: "Jobs", icon: "jobs" },
{ href: "/tokens", label: "Tokens", icon: "tokens" },
{ href: "/", label: "Tableau de bord", icon: "dashboard" },
{ href: "/books", label: "Livres", icon: "books" },
{ href: "/series", label: "Séries", icon: "series" },
{ href: "/libraries", label: "Bibliothèques", icon: "libraries" },
{ href: "/jobs", label: "Tâches", icon: "jobs" },
{ href: "/tokens", label: "Jetons", icon: "tokens" },
];
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<html lang="fr" suppressHydrationWarning>
<body className="min-h-screen bg-background text-foreground font-sans antialiased bg-grain">
<ThemeProvider>
{/* Header avec effet glassmorphism */}
@@ -76,7 +76,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
<Link
href="/settings"
className="hidden md:flex p-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
title="Settings"
title="Paramètres"
>
<Icon name="settings" size="md" />
</Link>