From 2fa3764df541c748f352dc10c7d3acadb9bcadee Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 17 May 2026 21:12:13 -0400 Subject: [PATCH] feat(ssr): pass library data to collection page templates Update frontend route handlers for /collections and /collections/:id to fetch user-visible libraries and pass libData + currentLibraryID to templates, enabling the library switcher dropdown. /collections handler: - Fetch GetUserVisibleLibraries for the current user - Derive currentLibraryID from query param, falling back to first library - Convert to []templates.LibraryData and pass to Collection template /collections/:id handler: - Fetch GetUserVisibleLibraries alongside existing book fetching - Pass libData to CollectionDetail template alongside existing libraryID - Refactored to use shared libraryID variable across system/user paths --- internal/router/frontend.go | 84 ++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/internal/router/frontend.go b/internal/router/frontend.go index fb8d318..a19fa28 100644 --- a/internal/router/frontend.go +++ b/internal/router/frontend.go @@ -585,8 +585,32 @@ func registerFrontendRoutes(cfg *Config) { } } + userUUID, _ := uuid.Parse(user.ID) + libraries, libErr := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID)) + if libErr != nil { + log.Printf("GetUserVisibleLibraries failed: %v", libErr) + libraries = []database.GetUserVisibleLibrariesRow{} + } + + currentLibraryID := c.QueryParam("library_id") + if currentLibraryID == "" && len(libraries) > 0 { + libUUID, _ := uuid.FromBytes(libraries[0].ID.Bytes[0:16]) + currentLibraryID = libUUID.String() + } + + libData := make([]templates.LibraryData, len(libraries)) + for i, lib := range libraries { + libUUID, _ := uuid.FromBytes(lib.ID.Bytes[0:16]) + libData[i] = templates.LibraryData{ + ID: libUUID.String(), + Name: lib.Name, + Description: getText(lib.Description), + TypeName: lib.TypeName, + } + } + var buf bytes.Buffer - err = templates.Collection(user, colData, errorMsg).Render(c.Request().Context(), &buf) + err = templates.Collection(user, colData, libData, currentLibraryID, errorMsg).Render(c.Request().Context(), &buf) if err != nil { return err } @@ -674,14 +698,12 @@ func registerFrontendRoutes(cfg *Config) { userUUID, _ := uuid.Parse(user.ID) var books []handlers.BookInfo + libraryID := c.QueryParam("library_id") + if collection.QueryType.Valid && collection.QueryType.String != "" { - // System collection - use query type - // System collection - need library_id for system collections - // Get library_id from query param or default to user's first library - libraryID := c.QueryParam("library_id") if libraryID == "" { - libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID)) - if err == nil && len(libraries) > 0 { + libraries, libErr := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID)) + if libErr == nil && len(libraries) > 0 { libUUID, _ := uuid.FromBytes(libraries[0].ID.Bytes[0:16]) libraryID = libUUID.String() } @@ -689,15 +711,13 @@ func registerFrontendRoutes(cfg *Config) { libUUID, _ := uuid.Parse(libraryID) dashboardSvc := services.NewDashboardService(cfg.Queries) - sections, err := dashboardSvc.GetDashboardSections(c.Request().Context(), userUUID, libUUID, 1000, []string{}, []string{}) - if err != nil { + sections, secErr := dashboardSvc.GetDashboardSections(c.Request().Context(), userUUID, libUUID, 1000, []string{}, []string{}) + if secErr != nil { return renderErrorPage(c, "Error loading books", "books_load_error") } - // Find the matching section and convert items for _, section := range sections { if section.CollectionID.String() == collectionID { - // Convert []database.MediaItems to []handlers.BookInfo bookCards := make([]handlers.BookInfo, len(section.Items)) for i, item := range section.Items { itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16]) @@ -713,27 +733,21 @@ func registerFrontendRoutes(cfg *Config) { } } } else { - // User collection - check if library_id filter is present - libraryID := c.QueryParam("library_id") - if libraryID != "" { - // Filter by library - reuse dashboard query - libUUID, err := uuid.Parse(libraryID) - if err != nil { + libUUID, parseErr := uuid.Parse(libraryID) + if parseErr != nil { return renderErrorPage(c, "Invalid library ID", "invalid_library_id") } - // Use GetCollectionItemsForDashboard for library-filtered results - collItems, err := cfg.Queries.GetCollectionItemsForDashboard(c.Request().Context(), + collItems, collErr := cfg.Queries.GetCollectionItemsForDashboard(c.Request().Context(), database.GetCollectionItemsForDashboardParams{ CollectionID: pgtype.UUID{Bytes: collUUID, Valid: true}, LibraryID: pgtype.UUID{Bytes: libUUID, Valid: true}, Limit: 1000, }) - if err != nil { + if collErr != nil { books = []handlers.BookInfo{} } else { - // Convert to BookInfo format (non-excluded only) var validItems []database.GetCollectionItemsForDashboardRow for _, item := range collItems { if !item.Excluded.Valid || !item.Excluded.Bool { @@ -754,13 +768,11 @@ func registerFrontendRoutes(cfg *Config) { books = bookCards } } else { - // No library filter - show all books in collection - collItems, err := cfg.Queries.GetCollectionItems(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true}) - if err != nil { + collItems, collErr := cfg.Queries.GetCollectionItems(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true}) + if collErr != nil { books = []handlers.BookInfo{} } - // Convert to BookInfo format bookCards := make([]handlers.BookInfo, len(collItems)) for i, item := range collItems { itemUUID, _ := uuid.FromBytes(item.MediaItemID.Bytes[0:16]) @@ -783,11 +795,25 @@ func registerFrontendRoutes(cfg *Config) { Icon: collection.Icon.String, } - // Get library_id from query params for template - libraryID := c.QueryParam("library_id") - // Render the CollectionDetail template + libraries, libErr := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID)) + if libErr != nil { + log.Printf("GetUserVisibleLibraries failed: %v", libErr) + libraries = []database.GetUserVisibleLibrariesRow{} + } + + libData := make([]templates.LibraryData, len(libraries)) + for i, lib := range libraries { + libUUID, _ := uuid.FromBytes(lib.ID.Bytes[0:16]) + libData[i] = templates.LibraryData{ + ID: libUUID.String(), + Name: lib.Name, + Description: getText(lib.Description), + TypeName: lib.TypeName, + } + } + var buf bytes.Buffer - err = templates.CollectionDetail(user, colData, books, libraryID).Render(c.Request().Context(), &buf) + err = templates.CollectionDetail(user, colData, books, libraryID, libData).Render(c.Request().Context(), &buf) if err != nil { return err }