refactor(templates): generalize SeriesDetail into reusable BrowseDetail
Replace the single-purpose SeriesDetail template with a parameterized BrowseDetail component that accepts badge icon/label, title, page title, back URL/label, empty state icon/message, and book list. Both series detail and new tag detail pages use the same template with different params, eliminating duplication. Series detail: 📚 Series, back to /series, "All Series" Tag detail: 🏷️ Tag, back to /bookshelf, "Bookshelf" Deleted series_detail.templ and series_detail_templ.go. Updated frontend.go series route to call BrowseDetail with series params. Added /tags/detail route calling BrowseDetail with tag params.
This commit is contained in:
@@ -269,7 +269,71 @@ func registerFrontendRoutes(cfg *Config) {
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = templates.SeriesDetail(user, seriesName, bookInfoList, libraryID, errorMsg).Render(c.Request().Context(), &buf)
|
||||
err = templates.BrowseDetail(user, "📚", "Series", seriesName, seriesName, "/series", "All Series", "📚", "This series doesn't have any books in this library yet", bookInfoList, errorMsg).Render(c.Request().Context(), &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HTML(http.StatusOK, buf.String())
|
||||
})
|
||||
|
||||
frontendProtected.GET("/tags/detail", func(c *echo.Context) error {
|
||||
user, err := getTemplateUserWithTheme(c, cfg)
|
||||
if err != nil {
|
||||
return renderErrorPage(c, "Error loading user", "user_load_error")
|
||||
}
|
||||
|
||||
var errorMsg string
|
||||
|
||||
tagName := c.QueryParam("name")
|
||||
if tagName == "" {
|
||||
return renderErrorPage(c, "Tag name required", "bad_request")
|
||||
}
|
||||
|
||||
libraryID := c.QueryParam("library_id")
|
||||
userUUID, _ := uuid.Parse(user.ID)
|
||||
if libraryID == "" {
|
||||
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()
|
||||
} else {
|
||||
errorMsg = "No libraries available"
|
||||
}
|
||||
}
|
||||
|
||||
var bookInfoList []handlers.BookInfo
|
||||
|
||||
if libraryID != "" && errorMsg == "" {
|
||||
libUUID, err := uuid.Parse(libraryID)
|
||||
if err == nil {
|
||||
books, err := cfg.Queries.GetBooksByTag(c.Request().Context(), database.GetBooksByTagParams{
|
||||
LibraryID: uuidToPGType(libUUID),
|
||||
Column2: tagName,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("GetBooksByTag failed: %v", err)
|
||||
errorMsg = "Error loading tag books"
|
||||
} else {
|
||||
bookInfoList = make([]handlers.BookInfo, 0, len(books))
|
||||
for _, item := range books {
|
||||
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
|
||||
bookInfoList = append(bookInfoList, handlers.BookInfo{
|
||||
MediaItemID: itemUUID.String(),
|
||||
Title: item.Title,
|
||||
Author: textToString(item.Author),
|
||||
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bookInfoList == nil {
|
||||
bookInfoList = []handlers.BookInfo{}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = templates.BrowseDetail(user, "🏷️", "Tag", tagName, tagName, "/bookshelf", "Bookshelf", "🏷️", "No books found with this tag", bookInfoList, errorMsg).Render(c.Request().Context(), &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user