search-song.go (1881B)
1 package server 2 3 import ( 4 "context" 5 "errors" 6 "lyrics/internal/db" 7 "lyrics/internal/domain" 8 "lyrics/internal/server/htmx" 9 songsearchtable "lyrics/internal/server/ui/partials/song-search-table" 10 "net/http" 11 "strconv" 12 ) 13 14 func (ss *ServerState) SearchSong(w http.ResponseWriter, r *http.Request) { 15 logger := ss.logger.With("handler", "SearchSong") 16 17 format := domain.SearchFormat(r.URL.Query().Get("format")) 18 query := r.URL.Query().Get("query") 19 20 pageStr := r.URL.Query().Get("page") 21 limitStr := r.URL.Query().Get("limit") 22 23 if pageStr == "" { 24 pageStr = "1" 25 } 26 27 page, err := strconv.ParseInt(pageStr, 10, 64) 28 if err != nil { 29 logger.Error("failed to parse page value", "err", err) 30 page = 1 31 } 32 if page <= 0 { 33 page = 1 34 } 35 36 if limitStr == "" { 37 limitStr = "25" 38 } 39 40 limit, err := strconv.ParseInt(limitStr, 10, 64) 41 if err != nil { 42 logger.Error("failed to parse limit value", "err", err) 43 limit = 25 44 } 45 if limit < 1 { 46 limit = 25 47 } 48 if limit > 100 { 49 limit = 100 50 } 51 52 offset := (page - 1) * limit 53 54 totalRows, results, err := db.SearchSong(ss.db, query, limit, offset) 55 if err != nil { 56 logger.Error("failed to query db for releases", "err", err) 57 htmx.HxError(w, http.StatusInternalServerError, "Failed to search for song.") 58 return 59 } 60 61 totalPages := (int64(totalRows) + limit - 1) / limit 62 63 var renderErr error 64 switch format { 65 case domain.SearchFormatTable: 66 renderErr = songsearchtable.SongSearchTable(songsearchtable.SongSearchTableParams{ 67 Songs: results, 68 TotalPages: int64(totalPages), 69 CurrentPage: page, 70 Query: query, 71 Limit: limit, 72 }).Render(r.Context(), w) 73 } 74 if renderErr != nil { 75 if errors.Is(renderErr, context.Canceled) { 76 return 77 } 78 79 logger.Error("failed to render search song partial", "err", renderErr) 80 htmx.HxError(w, http.StatusInternalServerError, "Failed to render response.") 81 return 82 } 83 }