feat: add genres filter to browse page
This commit is contained in:
@@ -119,11 +119,24 @@ func (h *Handler) HandleBrowse(w http.ResponseWriter, r *http.Request) {
|
||||
orderBy := r.URL.Query().Get("order_by")
|
||||
sort := r.URL.Query().Get("sort")
|
||||
|
||||
res, err := h.jikanClient.SearchAdvanced(r.Context(), q, animeType, status, orderBy, sort, 1, 24)
|
||||
var genres []int
|
||||
for _, g := range r.URL.Query()["genres"] {
|
||||
id, err := strconv.Atoi(g)
|
||||
if err == nil {
|
||||
genres = append(genres, id)
|
||||
}
|
||||
}
|
||||
|
||||
res, err := h.jikanClient.SearchAdvanced(r.Context(), q, animeType, status, orderBy, sort, genres, 1, 24)
|
||||
if err != nil {
|
||||
log.Printf("browse error: %v", err)
|
||||
}
|
||||
|
||||
genresList, err := h.jikanClient.GetAnimeGenres(r.Context())
|
||||
if err != nil {
|
||||
log.Printf("genres error: %v", err)
|
||||
}
|
||||
|
||||
watchlistMap := make(map[int64]bool)
|
||||
var watchlistIDs []int64
|
||||
if user != nil {
|
||||
@@ -137,12 +150,14 @@ func (h *Handler) HandleBrowse(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err := templates.GetRenderer().ExecuteTemplate(w, "browse.gohtml", map[string]any{
|
||||
"User": user,
|
||||
"CurrentPath": r.URL.Path,
|
||||
"CurrentPath": r.URL.Path,
|
||||
"Query": q,
|
||||
"Type": animeType,
|
||||
"Status": status,
|
||||
"OrderBy": orderBy,
|
||||
"Sort": sort,
|
||||
"Genres": genres,
|
||||
"GenresList": genresList,
|
||||
"Animes": res.Animes,
|
||||
"WatchlistMap": watchlistMap,
|
||||
"WatchlistIDs": watchlistIDs,
|
||||
@@ -255,7 +270,7 @@ func (h *Handler) HandleQuickSearch(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode([]quickSearchResult{})
|
||||
return
|
||||
}
|
||||
res, err := h.jikanClient.SearchAdvanced(r.Context(), query, "", "", "", "", 1, 5)
|
||||
res, err := h.jikanClient.SearchAdvanced(r.Context(), query, "", "", "", "", nil, 1, 5)
|
||||
if err != nil {
|
||||
log.Printf("quick search error: %v", err)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
@@ -3,3 +3,4 @@ package jikan
|
||||
import "time"
|
||||
|
||||
const shortCacheTTL = time.Hour
|
||||
const longCacheTTL = time.Hour * 24
|
||||
|
||||
@@ -4,13 +4,15 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Client) Search(ctx context.Context, query string, page int) (SearchResult, error) {
|
||||
return c.search(ctx, query, page, 0)
|
||||
}
|
||||
|
||||
func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, orderBy, sort string, page, limit int) (SearchResult, error) {
|
||||
func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, orderBy, sort string, genres []int, page, limit int) (SearchResult, error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
@@ -18,7 +20,16 @@ func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, o
|
||||
limit = 0
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("search:%s:%s:%s:%s:%s:%d:%d", query, animeType, status, orderBy, sort, page, limit)
|
||||
genresParam := ""
|
||||
if len(genres) > 0 {
|
||||
ids := make([]string, len(genres))
|
||||
for i, g := range genres {
|
||||
ids[i] = strconv.Itoa(g)
|
||||
}
|
||||
genresParam = strings.Join(ids, ",")
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("search:%s:%s:%s:%s:%s:%s:%d:%d", query, animeType, status, orderBy, sort, genresParam, page, limit)
|
||||
|
||||
var result SearchResponse
|
||||
reqURL := fmt.Sprintf("%s/anime?page=%d", c.baseURL, page)
|
||||
@@ -37,6 +48,9 @@ func (c *Client) SearchAdvanced(ctx context.Context, query, animeType, status, o
|
||||
if sort != "" {
|
||||
reqURL += "&sort=" + url.QueryEscape(sort)
|
||||
}
|
||||
if genresParam != "" {
|
||||
reqURL += "&genres=" + genresParam
|
||||
}
|
||||
if limit > 0 {
|
||||
reqURL += fmt.Sprintf("&limit=%d", limit)
|
||||
}
|
||||
@@ -127,3 +141,16 @@ func (c *Client) GetTopAnime(ctx context.Context, page int) (TopAnimeResult, err
|
||||
HasNextPage: result.Pagination.HasNextPage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetAnimeGenres(ctx context.Context) ([]Genre, error) {
|
||||
const cacheKey = "anime_genres"
|
||||
|
||||
var result GenresResponse
|
||||
reqURL := fmt.Sprintf("%s/genres/anime", c.baseURL)
|
||||
|
||||
if err := c.getWithCache(ctx, cacheKey, longCacheTTL, reqURL, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
@@ -143,6 +143,15 @@ type AnimeResponse struct {
|
||||
Data Anime `json:"data"`
|
||||
}
|
||||
|
||||
type Genre struct {
|
||||
MalID int `json:"mal_id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type GenresResponse struct {
|
||||
Data []Genre `json:"data"`
|
||||
}
|
||||
|
||||
type SearchResponse struct {
|
||||
Data []Anime `json:"data"`
|
||||
Pagination Pagination `json:"pagination"`
|
||||
|
||||
Reference in New Issue
Block a user