feat: display missing books count badge on series covers

Show an orange badge with BookX icon on series covers when the Stripstream
API reports missing books in the collection. Also display a warning status
badge on the series detail page header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-20 13:17:53 +01:00
parent f48d894eca
commit a82ce024ee
7 changed files with 20 additions and 2 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { Book, BookOpen, BookMarked, Star, StarOff, User } from "lucide-react";
import { Book, BookOpen, BookMarked, BookX, Star, StarOff, User } from "lucide-react";
import type { NormalizedSeries } from "@/lib/providers/types";
import { useState, useEffect } from "react";
import { useToast } from "@/components/ui/use-toast";
@@ -160,6 +160,11 @@ export const SeriesHeader = ({ series, refreshSeries, initialIsFavorite }: Serie
? t("series.header.books", { count: series.bookCount })
: t("series.header.books_plural", { count: series.bookCount })}
</span>
{series.missingCount != null && series.missingCount > 0 && (
<StatusBadge status="warning" icon={BookX}>
{t("series.header.missing", { count: series.missingCount })}
</StatusBadge>
)}
<IconButton
variant="ghost"
size="icon"

View File

@@ -1,4 +1,5 @@
import { ProgressBar } from "./progress-bar";
import { BookX } from "lucide-react";
import type { SeriesCoverProps } from "./cover-utils";
export function SeriesCover({
@@ -12,6 +13,7 @@ export function SeriesCover({
const readBooks = series.booksReadCount;
const totalBooks = series.bookCount;
const showProgress = Boolean(showProgressUi && totalBooks > 0 && readBooks > 0 && !isCompleted);
const missingCount = series.missingCount;
return (
<div className="relative w-full h-full">
@@ -27,6 +29,12 @@ export function SeriesCover({
.filter(Boolean)
.join(" ")}
/>
{showProgressUi && missingCount != null && missingCount > 0 && (
<div className="absolute top-1.5 right-1.5 flex items-center gap-0.5 rounded-full bg-orange-500/90 px-1.5 py-0.5 text-white shadow-md backdrop-blur-sm">
<BookX className="h-3 w-3" />
<span className="text-[10px] font-bold leading-none">{missingCount}</span>
</div>
)}
{showProgress ? <ProgressBar progress={readBooks} total={totalBooks} type="series" /> : null}
</div>
);

View File

@@ -263,6 +263,7 @@
},
"showMore": "Show more",
"showLess": "Show less",
"missing": "{{count}} missing",
"toggleSidebar": "Toggle sidebar",
"toggleTheme": "Toggle theme"
}

View File

@@ -262,7 +262,8 @@
"remove": "Retiré des favoris"
},
"showMore": "Voir plus",
"showLess": "Voir moins"
"showLess": "Voir moins",
"missing": "{{count}} manquant(s)"
}
},
"books": {

View File

@@ -79,6 +79,7 @@ export class StripstreamAdapter {
genres: [],
tags: [],
createdAt: null,
missingCount: series.missing_count ?? null,
};
}

View File

@@ -25,6 +25,7 @@ export interface NormalizedSeries {
genres?: string[];
tags?: string[];
createdAt?: string | null;
missingCount?: number | null;
}
export interface NormalizedBook {

View File

@@ -49,6 +49,7 @@ export interface StripstreamSeriesItem {
books_read_count: number;
first_book_id: string;
library_id: string;
missing_count?: number | null;
}
export interface StripstreamSeriesPage {