refactor: update handlers to use unified search endpoint

- Update SearchMediaItems handler to use SearchService
- Add autocomplete detection for field value queries (author=value, genre=value, etc.)
- Add handleFieldValuesSearch method for dropdown population
- Add sort parameter extraction with default "title ASC"
- Remove deprecated ListMediaItemsFiltered handler
- Remove deprecated /api/media-items/filtered route registration
- Update frontend.go to use SearchMediaItemsUnified instead of ListMediaItemsFiltered
- Fix parameter passing (empty filters use Valid:true with empty values, not Valid:false)
- Add SearchQuery, IsExactSearch, SearchPattern parameters for query parsing

Handler is now a thin wrapper that extracts params and delegates to service layer.
This commit is contained in:
2026-03-23 22:37:44 -04:00
parent 871d5eafe6
commit 172536f888
3 changed files with 20 additions and 74 deletions
+13 -10
View File
@@ -175,7 +175,7 @@ func registerFrontendRoutes(cfg *Config) {
}
// Fetch first page of books for SSR
var books []database.ListMediaItemsFilteredRow
var books []database.SearchMediaItemsUnifiedRow
var bookInfoList []handlers.BookInfo
totalCount := 0
limit := 50
@@ -196,23 +196,26 @@ func registerFrontendRoutes(cfg *Config) {
}
}
books, err = cfg.Queries.ListMediaItemsFiltered(c.Request().Context(), database.ListMediaItemsFilteredParams{
books, err = cfg.Queries.SearchMediaItemsUnified(c.Request().Context(), database.SearchMediaItemsUnifiedParams{
LibraryID: pgtype.UUID{Bytes: libUUID, Valid: true},
UserID: pgtype.UUID{Bytes: userUUID, Valid: true},
AuthorFilter: pgtype.Text{String: "", Valid: false},
SeriesFilter: pgtype.Text{String: "", Valid: false},
GenreFilter: pgtype.Text{String: "", Valid: false},
LanguageFilter: pgtype.Text{String: "", Valid: false},
YearMin: pgtype.Int4{Valid: false},
YearMax: pgtype.Int4{Valid: false},
HasCover: pgtype.Bool{Valid: false},
AuthorFilter: pgtype.Text{String: "", Valid: true}, // Changed: Valid=true for empty string
SeriesFilter: pgtype.Text{String: "", Valid: true}, // Changed
GenreFilter: pgtype.Text{String: "", Valid: true}, // Changed
LanguageFilter: pgtype.Text{String: "", Valid: true}, // Changed
YearMin: pgtype.Int4{Int32: 0, Valid: true}, // Changed: use 0 as default
YearMax: pgtype.Int4{Int32: 0, Valid: true}, // Changed
HasCover: pgtype.Bool{Bool: false, Valid: true}, // Changed
SearchQuery: pgtype.Text{String: "", Valid: true}, // NEW: Required
IsExactSearch: pgtype.Bool{Bool: false, Valid: true}, // NEW: Required
SearchPattern: pgtype.Text{Valid: false}, // NEW: Empty for no exact search
Sort: pgtype.Text{String: "created_at DESC", Valid: true},
Limit: pgtype.Int4{Int32: int32(limit), Valid: true},
Offset: pgtype.Int4{Int32: int32(offset), Valid: true},
})
if err != nil {
log.Printf("ListMediaItemsFiltered failed: %v", err)
log.Printf("SearchMediaItemsUnified failed: %v", err)
// Continue without books - will show empty state
} else {
// Convert database rows to BookInfo structs (matching BuildSections pattern)