From 23765934ef75899183149a0d6297f63615bedfa0 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 17 Oct 2026 14:02:16 -0400 Subject: [PATCH] refactor(cards): collections JSON detail + preview-adjacent ladder through the builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GET /api/collections/:id books — all four branches now build cards via the cards.go adapters. LibraryTypeMap hoisted to once per handler (it was 1 query per item in the smart and no-library branches). The system branch — which before stamped cards BARE (no format_group, no badge — the ladder's only JSON gap) — now emits the same card shape as its siblings by feeding section.Items through BookCardsFromMediaItems, matching what BuildSections produces for the identical data. The collection-error seed dies via the adapters' non-nil empty slices; the no-matching-section nil result is preserved as-is (that branch never seeded — today's 'items': null stays today's 'items': null). Pins: CollectionsJSON, DashboardSections, MediaListBothBranches green. --- internal/handlers/collections.go | 57 ++++---------------------------- 1 file changed, 6 insertions(+), 51 deletions(-) diff --git a/internal/handlers/collections.go b/internal/handlers/collections.go index 6e522e8b..997b6317 100644 --- a/internal/handlers/collections.go +++ b/internal/handlers/collections.go @@ -254,6 +254,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { } isSmart := h.collectionService.IsSmartCollection(collection.AutoAssignRules) + libTypes := LibraryTypeMap(c.Request().Context(), h.db) if isSmart { rules := h.collectionService.ParseRules(collection.AutoAssignRules) visibleIDs, err := h.userVisibleLibraryIDs(c) @@ -267,19 +268,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { if evalErr != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": evalErr.Error()}) } - bookList = make([]BookInfo, 0, len(matches)) - for _, item := range matches { - itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16]) - libTypes := LibraryTypeMap(c.Request().Context(), h.db) - bookList = append(bookList, BookInfo{ - MediaItemID: itemUUID.String(), - Title: item.Title, - Author: textToString(item.Author), - CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath), - FormatGroup: item.FormatGroup, - Badge: MediaBadgeKind(item.FormatGroup, libTypes[uuid.UUID(item.LibraryID.Bytes).String()]), - }) - } + bookList = BookCardsFromMediaItems(matches, libTypes) } else if collection.IsSystemCollection.Bool && collection.QueryType.Valid && collection.QueryType.String != "" && collection.QueryType.String != "filter" { user := c.Get("user").(database.Users) userUUID := uuid.UUID(user.ID.Bytes) @@ -290,17 +279,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { } for _, section := range sections { if section.CollectionID == collectionID { - bookCards := make([]BookInfo, len(section.Items)) - for i, item := range section.Items { - itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16]) - bookCards[i] = BookInfo{ - MediaItemID: itemUUID.String(), - Title: item.Title, - Author: textToString(item.Author), - CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath), - } - } - bookList = bookCards + bookList = BookCardsFromMediaItems(section.Items, libTypes) break } } @@ -312,7 +291,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { Limit: pgtype.Int4{Int32: 10000, Valid: true}, }) if collErr != nil { - bookList = []BookInfo{} + bookList = BookCardsFromCollectionDashRows(nil, libTypes) } else { var validItems []database.GetCollectionItemsForDashboardRow for _, item := range collItems { @@ -320,38 +299,14 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error { validItems = append(validItems, item) } } - libTypes := LibraryTypeMap(c.Request().Context(), h.db) - bookCards := make([]BookInfo, len(validItems)) - for i, item := range validItems { - itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16]) - bookCards[i] = BookInfo{ - MediaItemID: itemUUID.String(), - Title: item.Title, - Author: textToString(item.Author), - CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath), - FormatGroup: item.FormatGroup, - Badge: MediaBadgeKind(item.FormatGroup, libTypes[uuid.UUID(item.LibraryID.Bytes).String()]), - } - } - bookList = bookCards + bookList = BookCardsFromCollectionDashRows(validItems, libTypes) } } else { books, booksErr := h.GetCollectionBooksData(c, collectionID) if booksErr != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": booksErr.Error()}) } - bookList = make([]BookInfo, 0, len(books)) - for _, book := range books { - libTypes := LibraryTypeMap(c.Request().Context(), h.db) - bookList = append(bookList, BookInfo{ - MediaItemID: uuid.UUID(book.MediaItemID.Bytes).String(), - Title: book.Title, - Author: textToString(book.Author), - CoverImagePath: utils.ResolveMediaURL(book.LibraryID, book.CoverImagePath), - FormatGroup: book.FormatGroup, - Badge: MediaBadgeKind(book.FormatGroup, libTypes[uuid.UUID(book.LibraryID.Bytes).String()]), - }) - } + bookList = BookCardsFromCollectionItemRows(books, libTypes) } var viewSettings map[string]interface{}