From a82ce024ee68e797b958680dd6b9b3d9f3a4eaab Mon Sep 17 00:00:00 2001 From: Froidefond Julien Date: Fri, 20 Mar 2026 13:17:53 +0100 Subject: [PATCH] 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 --- src/components/series/SeriesHeader.tsx | 7 ++++++- src/components/ui/series-cover.tsx | 8 ++++++++ src/i18n/messages/en/common.json | 1 + src/i18n/messages/fr/common.json | 3 ++- src/lib/providers/stripstream/stripstream.adapter.ts | 1 + src/lib/providers/types.ts | 1 + src/types/stripstream.ts | 1 + 7 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/series/SeriesHeader.tsx b/src/components/series/SeriesHeader.tsx index 57e3835..6f8dd27 100644 --- a/src/components/series/SeriesHeader.tsx +++ b/src/components/series/SeriesHeader.tsx @@ -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 })} + {series.missingCount != null && series.missingCount > 0 && ( + + {t("series.header.missing", { count: series.missingCount })} + + )} 0 && readBooks > 0 && !isCompleted); + const missingCount = series.missingCount; return (
@@ -27,6 +29,12 @@ export function SeriesCover({ .filter(Boolean) .join(" ")} /> + {showProgressUi && missingCount != null && missingCount > 0 && ( +
+ + {missingCount} +
+ )} {showProgress ? : null}
); diff --git a/src/i18n/messages/en/common.json b/src/i18n/messages/en/common.json index 3ba0969..4ce593e 100644 --- a/src/i18n/messages/en/common.json +++ b/src/i18n/messages/en/common.json @@ -263,6 +263,7 @@ }, "showMore": "Show more", "showLess": "Show less", + "missing": "{{count}} missing", "toggleSidebar": "Toggle sidebar", "toggleTheme": "Toggle theme" } diff --git a/src/i18n/messages/fr/common.json b/src/i18n/messages/fr/common.json index 9d531c1..d5d75d3 100644 --- a/src/i18n/messages/fr/common.json +++ b/src/i18n/messages/fr/common.json @@ -262,7 +262,8 @@ "remove": "Retiré des favoris" }, "showMore": "Voir plus", - "showLess": "Voir moins" + "showLess": "Voir moins", + "missing": "{{count}} manquant(s)" } }, "books": { diff --git a/src/lib/providers/stripstream/stripstream.adapter.ts b/src/lib/providers/stripstream/stripstream.adapter.ts index 679c2a1..5ba798f 100644 --- a/src/lib/providers/stripstream/stripstream.adapter.ts +++ b/src/lib/providers/stripstream/stripstream.adapter.ts @@ -79,6 +79,7 @@ export class StripstreamAdapter { genres: [], tags: [], createdAt: null, + missingCount: series.missing_count ?? null, }; } diff --git a/src/lib/providers/types.ts b/src/lib/providers/types.ts index d581315..57f9ee8 100644 --- a/src/lib/providers/types.ts +++ b/src/lib/providers/types.ts @@ -25,6 +25,7 @@ export interface NormalizedSeries { genres?: string[]; tags?: string[]; createdAt?: string | null; + missingCount?: number | null; } export interface NormalizedBook { diff --git a/src/types/stripstream.ts b/src/types/stripstream.ts index 03437c5..d116728 100644 --- a/src/types/stripstream.ts +++ b/src/types/stripstream.ts @@ -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 {