feat: Add collection detail page with /collections/:id route
Add comprehensive collection detail page that works for both system collections
(continue-reading, recently-added, not-started) and user collections.
Backend changes:
- Add new /collections/:id route in internal/router/frontend.go
- Fetches collection using GetCollection with UUID parameter
- Determines collection type from QueryType field
- Resolves library_id for system collections
- Converts database.MediaItems to handlers.BookInfo for display
- Renders CollectionDetail template with collection and books data
- Update SectionData struct in internal/handlers/collections.go
- Add CollectionID string field for view all links
- Update BuildSections() in internal/handlers/dashboard.go
- Pass CollectionID to SectionData for proper link generation
- Simplify getViewAllURL() in internal/handlers/dashboard.go
- Return /collections/{collectionID} instead of /section/{type}
- Works uniformly for both system and user collections
Frontend changes:
- Fix CollectionDetail template in templates/collections.templ
- Fix broken div nesting causing compilation error
- Add null check for CoverImagePath to prevent broken images
- Update aspect ratio to modern aspect-[3/4] syntax
- Use responsive widths (w-16 sm:w-20) for mobile/desktop
- Improve card layout with horizontal flex structure
- Add placeholder image fallback for books without covers
- Remove erroneous renderBooks() function call
This change aligns with the backend update where system collections are
now pre-made user collections in the database with query_type fields.
All collections can now use the same CollectionDetail template for a
consistent viewing experience.
This commit is contained in:
@@ -196,7 +196,7 @@ func (s *DashboardService) GetDashboardSections(
|
||||
})
|
||||
}
|
||||
|
||||
results = s.filterHiddenCollections(results, hiddenCollections)
|
||||
results = s.FilterHiddenCollections(results, hiddenCollections)
|
||||
results = s.reorderCollections(results, collectionOrder)
|
||||
|
||||
if len(collectionOrder) == 0 {
|
||||
@@ -206,7 +206,7 @@ func (s *DashboardService) GetDashboardSections(
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *DashboardService) filterHiddenCollections(sections []DashboardSection, hidden []string) []DashboardSection {
|
||||
func (s *DashboardService) FilterHiddenCollections(sections []DashboardSection, hidden []string) []DashboardSection {
|
||||
if len(hidden) == 0 {
|
||||
return sections
|
||||
}
|
||||
@@ -373,6 +373,30 @@ func (s *DashboardService) UpsertDashboardPreferences(ctx context.Context, param
|
||||
return s.db.UpsertDashboardPreferences(ctx, params)
|
||||
}
|
||||
|
||||
func (s *DashboardService) SanitizeDashboardPreferences(hiddenCollections, collectionOrder []string) ([]string, []string) {
|
||||
// Deduplicate collection_order while preserving order
|
||||
seen := make(map[string]bool)
|
||||
var sanitizedOrder []string
|
||||
for _, id := range collectionOrder {
|
||||
if !seen[id] {
|
||||
seen[id] = true
|
||||
sanitizedOrder = append(sanitizedOrder, id)
|
||||
}
|
||||
}
|
||||
|
||||
// Deduplicate hidden_collections
|
||||
seen = make(map[string]bool)
|
||||
var sanitizedHidden []string
|
||||
for _, id := range hiddenCollections {
|
||||
if !seen[id] {
|
||||
seen[id] = true
|
||||
sanitizedHidden = append(sanitizedHidden, id)
|
||||
}
|
||||
}
|
||||
|
||||
return sanitizedHidden, sanitizedOrder
|
||||
}
|
||||
|
||||
func (s *DashboardService) RestoreSystemCollection(ctx context.Context, userID uuid.UUID, collectionName string, resetType string) error {
|
||||
defaultMetadata := map[string]struct {
|
||||
Description string
|
||||
|
||||
Reference in New Issue
Block a user