feat: add infinite scroll to browse page

This commit is contained in:
2026-05-02 17:38:53 +02:00
committed by Mikkel Elvers
parent db9882329b
commit b0fe7bf061
3 changed files with 78 additions and 7 deletions

View File

@@ -127,23 +127,57 @@ func (h *Handler) HandleBrowse(w http.ResponseWriter, r *http.Request) {
}
}
res, err := h.jikanClient.SearchAdvanced(r.Context(), q, animeType, status, orderBy, sort, genres, 1, 24)
pageStr := r.URL.Query().Get("page")
page, _ := strconv.Atoi(pageStr)
if page < 1 {
page = 1
}
res, err := h.jikanClient.SearchAdvanced(r.Context(), q, animeType, status, orderBy, sort, genres, page, 24)
if err != nil {
log.Printf("browse error: %v", err)
}
if r.Header.Get("HX-Request") == "true" {
watchlistMap := make(map[int]bool)
if user != nil {
watchlist, _ := h.db.GetUserWatchList(r.Context(), user.ID)
for _, entry := range watchlist {
watchlistMap[int(entry.AnimeID)] = true
}
}
w.Header().Set("Content-Type", "text/html")
err := templates.GetRenderer().ExecuteFragment(w, "browse.gohtml", "anime_card_scroll", map[string]any{
"Animes": res.Animes,
"NextPage": page + 1,
"HasNextPage": res.HasNextPage,
"Query": q,
"Type": animeType,
"Status": status,
"OrderBy": orderBy,
"Sort": sort,
"Genres": genres,
"WatchlistMap": watchlistMap,
})
if err != nil {
log.Printf("fragment render error: %v", err)
}
return
}
genresList, err := h.jikanClient.GetAnimeGenres(r.Context())
if err != nil {
log.Printf("genres error: %v", err)
}
watchlistMap := make(map[int64]bool)
watchlistMap := make(map[int]bool)
var watchlistIDs []int64
if user != nil {
watchlist, _ := h.db.GetUserWatchList(r.Context(), user.ID)
watchlistIDs = make([]int64, len(watchlist))
for i, entry := range watchlist {
watchlistMap[entry.AnimeID] = true
watchlistMap[int(entry.AnimeID)] = true
watchlistIDs[i] = entry.AnimeID
}
}
@@ -159,6 +193,8 @@ func (h *Handler) HandleBrowse(w http.ResponseWriter, r *http.Request) {
"Genres": genres,
"GenresList": genresList,
"Animes": res.Animes,
"HasNextPage": res.HasNextPage,
"NextPage": page + 1,
"WatchlistMap": watchlistMap,
"WatchlistIDs": watchlistIDs,
}); err != nil {

View File

@@ -15,12 +15,41 @@
<p>No anime found matching your filters.</p>
</div>
{{else}}
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6">
{{range .Animes}}
{{template "anime_card" dict "Anime" . "WithActions" true "IsWatchlist" (index $.WatchlistMap .MalID)}}
<div id="anime-grid" class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6">
{{range $i, $anime := .Animes}}
{{$isThreshold := eq (add $i 1) (sub (len $.Animes) 8)}}
{{if and $isThreshold $.HasNextPage}}
<div hx-get="/browse?q={{$.Query}}&type={{$.Type}}&status={{$.Status}}&order_by={{$.OrderBy}}&sort={{$.Sort}}&{{genresParams $.Genres}}&page={{$.NextPage}}"
hx-trigger="revealed"
hx-swap="afterend"
hx-target="this"
class="contents">
{{template "anime_card" dict "Anime" . "WithActions" true "IsWatchlist" (index $.WatchlistMap .MalID)}}
</div>
{{else}}
{{template "anime_card" dict "Anime" . "WithActions" true "IsWatchlist" (index $.WatchlistMap .MalID)}}
{{end}}
{{end}}
</div>
{{end}}
</main>
</div>
{{end}}
{{end}}
{{define "anime_card_scroll"}}
{{$count := len .Animes}}
{{range $i, $anime := .Animes}}
{{$isThreshold := eq (add $i 1) (sub $count 8)}}
{{if and $isThreshold $.HasNextPage}}
<div hx-get="/browse?q={{$.Query}}&type={{$.Type}}&status={{$.Status}}&order_by={{$.OrderBy}}&sort={{$.Sort}}&{{genresParams $.Genres}}&page={{$.NextPage}}"
hx-trigger="revealed"
hx-swap="afterend"
hx-target="this"
class="contents">
{{template "anime_card" dict "Anime" $anime "WithActions" true "IsWatchlist" (index $.WatchlistMap $anime.MalID)}}
</div>
{{else}}
{{template "anime_card" dict "Anime" $anime "WithActions" true "IsWatchlist" (index $.WatchlistMap $anime.MalID)}}
{{end}}
{{end}}
{{end}}

View File

@@ -59,6 +59,12 @@ func GetRenderer() *Renderer {
}
return false
},
"add": func(a, b int) int {
return a + b
},
"sub": func(a, b int) int {
return a - b
},
}
pages, err := filepath.Glob(filepath.Join(".", "templates", "*.gohtml"))