From 77c7ef965feabd4a43a6cadb797b5552422c31c3 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Thu, 19 Feb 2026 21:11:40 -0500 Subject: [PATCH] feat(dashboard): implement Phase 8 SSR template routes for Carousel-style dashboard Update /dashboard route in frontend.go to use unified collections architecture: Route Changes: - Use DashboardService to fetch user dashboard preferences - Get all dashboard sections (system + user collections) - Pass sections and library data to template - Support library_id query parameter for library switching - Default to first visible library if no library_id specified Service Integration: - cfg.DashboardService.GetDashboardPreferences: Fetch user preferences * hidden_collections: Collections to hide from dashboard * collection_order: Custom collection ordering * items_per_section: Number of items per collection - cfg.DashboardService.GetDashboardSections: Fetch all sections * System collections (user_id = NULL): continue-reading, recently-added, recently-read, not-started * User collections: User-created collections marked for dashboard * Applies user preferences: filters hidden, reorders, sorts by priority - handlers.BuildSections: Convert service types to handler types Data Flow: 1. Get user template data with theme 2. Get library_id from query param or default to first library 3. Fetch user dashboard preferences 4. Fetch dashboard sections with preferences applied 5. Convert to handler types for template rendering 6. Render template with sections and library data Template Signature Change: - OLD: templates.Dashboard(user) - NEW: templates.Dashboard(user, sections, libData, currentLibraryID) This implements Phase 8: SSR Template Routes with unified collections architecture. --- internal/router/frontend.go | 49 ++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/internal/router/frontend.go b/internal/router/frontend.go index abe949a..566811f 100644 --- a/internal/router/frontend.go +++ b/internal/router/frontend.go @@ -107,8 +107,55 @@ func registerFrontendRoutes(cfg *Config) { if err != nil { return c.HTML(http.StatusInternalServerError, "Error loading user") } + + libraryID := c.QueryParam("library_id") + if libraryID == "" { + userUUID, _ := uuid.Parse(user.ID) + libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID)) + if err == nil && len(libraries) > 0 { + libUUID, _ := uuid.FromBytes(libraries[0].ID.Bytes[0:16]) + libraryID = libUUID.String() + } + } + + libUUID, _ := uuid.Parse(libraryID) + userUUID, _ := uuid.Parse(user.ID) + + prefs, _ := cfg.DashboardService.GetDashboardPreferences(c.Request().Context(), userUUID, libUUID) + + sections, err := cfg.DashboardService.GetDashboardSections( + c.Request().Context(), + userUUID, + libUUID, + int(prefs.ItemsPerSection.Int32), + prefs.CollectionOrder, + prefs.HiddenCollections, + ) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading dashboard") + } + + userUUID2, _ := uuid.Parse(user.ID) + libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID2)) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading libraries") + } + + 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, + } + } + + sectionData := handlers.BuildSections(sections) + var buf bytes.Buffer - err = templates.Dashboard(user).Render(c.Request().Context(), &buf) + err = templates.Dashboard(user, sectionData, libData, libraryID).Render(c.Request().Context(), &buf) if err != nil { return err }