From b2b89ba7897cf49843e2cf6c9ea4096fb24c4553 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 17 Oct 2026 14:08:45 -0400 Subject: [PATCH] feat(cards): stamp active conflicts on collections, series, and preview JSON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last behavior gap in the H2 batch: has_conflict was part of the frozen card shape but stamped false-forever on these three JSON surfaces (only dashboard sections, search, and the SSR pages had it), so every conflict-driven card action — the resolve-conflict CTA in BookCard — never fired there. MarkActiveConflicts now runs after the builder on GET /api/collections/:id, series books, and smart-collection preview (all user-scoped; the endpoint already authenticates). Key set is unchanged — has_conflict was always emitted, this only makes its value truthful. All 15 contract pins + H1 tests green; the pin's bookInfoKeys freeze unaffected. --- internal/handlers/collections.go | 7 +++++++ internal/handlers/series.go | 3 +++ 2 files changed, 10 insertions(+) diff --git a/internal/handlers/collections.go b/internal/handlers/collections.go index e77d8260..71d2f8e1 100644 --- a/internal/handlers/collections.go +++ b/internal/handlers/collections.go @@ -309,6 +309,10 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { bookList = BookCardsFromCollectionItemRows(books, libTypes) } + if u, ok := c.Get("user").(database.Users); ok { + bookList = MarkActiveConflicts(c.Request().Context(), h.db, u.ID, bookList) + } + var viewSettings map[string]interface{} if len(collection.ViewSettings) > 0 { err := json.Unmarshal(collection.ViewSettings, &viewSettings) @@ -1252,6 +1256,9 @@ func (h *CollectionHandler) PreviewCollection(c *echo.Context) error { } bookCards := BookCardsFromMediaItems(matchedItems, LibraryTypeMap(c.Request().Context(), h.db)) + if u, ok := c.Get("user").(database.Users); ok { + bookCards = MarkActiveConflicts(c.Request().Context(), h.db, u.ID, bookCards) + } return c.JSON(http.StatusOK, map[string]interface{}{"items": bookCards}) } diff --git a/internal/handlers/series.go b/internal/handlers/series.go index 37472605..51312991 100644 --- a/internal/handlers/series.go +++ b/internal/handlers/series.go @@ -153,6 +153,9 @@ func (h *SeriesHandler) GetSeriesBooks(c *echo.Context) error { } bookCards := BookCardsFromMediaItems(books, LibraryTypeMap(c.Request().Context(), h.db)) + if u, ok := c.Get("user").(database.Users); ok { + bookCards = MarkActiveConflicts(c.Request().Context(), h.db, u.ID, bookCards) + } return c.JSON(http.StatusOK, map[string]interface{}{ "name": seriesName,