Files
bookhoard/templates/series.templ
T
John O'Keefe f4414aa5b6 style(series): plain-text page indicator instead of the chip pill
"Page N of M" now renders as small secondary-color text on the page
background rather than an accent chip (user preference; the old TS
twin happened to render this way and the chip was only being seen
after JS took over). With the twin deleted, this templ markup is the
only paginator rendering, so the look is stable.
2026-10-19 12:39:20 -04:00

106 lines
4.0 KiB
Templ

package templates
import (
"fmt"
"net/url"
)
templ Series(user User, seriesList []SeriesCardData, libData []LibraryData, currentLibraryID string, totalPages int, currentPage int, errorMessage string) {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Series - Bookhoard</title>
<link href="/static/style.css" rel="stylesheet"/>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg"/>
</head>
<body x-data="seriesPage" x-init="initSeriesPage()" class={ "theme-" + user.Theme }>
@Header(user, "/series")
@LibrarySwitcher(libData, currentLibraryID, "")
<div id="series-container">
<main class="mx-auto container px-4 sm:px-6 lg:px-8 py-8">
<div class="mb-6 flex items-center gap-3">
<span class="grid place-items-center h-10 w-10 rounded-xl" style="background-color: var(--accent-muted); color: var(--accent);">
@Icon("layers", "h-5 w-5")
</span>
<div>
<h1 class="text-2xl font-bold tracking-tight" style="color: var(--text-primary)">Series</h1>
<p class="text-xs font-semibold uppercase tracking-wide" style="color: var(--text-secondary)">Grouped by series metadata</p>
</div>
</div>
if len(seriesList) == 0 {
<div id="series-empty" class="card text-center py-16 px-6">
<div class="grid place-items-center h-14 w-14 rounded-2xl mx-auto mb-4" style="background-color: var(--accent-muted); color: var(--accent);">
@Icon("layers", "h-7 w-7")
</div>
<h3 class="text-xl font-semibold mb-2" style="color: var(--text-primary)">No Series Found</h3>
<p style="color: var(--text-secondary)">Books with series metadata will appear here</p>
</div>
}
<div id="series-grid" class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-6">
for _, series := range seriesList {
@SeriesCard(series)
}
</div>
if totalPages > 1 {
<div id="series-pagination" class="flex justify-center items-center gap-3 mt-10">
if currentPage > 1 {
<a
href={ fmt.Sprintf("/series?library_id=%s&page=%d", currentLibraryID, currentPage-1) }
class="btn btn-secondary"
>
@Icon("chevron-left", "h-4 w-4")
<span>Previous</span>
</a>
}
<span class="text-sm" style="color: var(--text-secondary)">
Page { fmt.Sprintf("%d", currentPage) } of { fmt.Sprintf("%d", totalPages) }
</span>
if currentPage < totalPages {
<a
href={ fmt.Sprintf("/series?library_id=%s&page=%d", currentLibraryID, currentPage+1) }
class="btn btn-secondary"
>
<span>Next</span>
@Icon("chevron-right", "h-4 w-4")
</a>
}
</div>
}
</main>
</div>
@ErrorToast(errorMessage)
</body>
</html>
}
templ SeriesCard(series SeriesCardData) {
<a href={ "/series/detail?name=" + url.QueryEscape(series.Name) + "&library_id=" + url.QueryEscape(series.LibraryID) } class="block">
<div class="series-card card rounded-2xl overflow-hidden cursor-pointer" style="box-shadow: var(--shadow-card);">
<div class={ "stacked-covers cover-count-" + fmt.Sprintf("%d", len(series.CoverPaths)) }>
for i, cover := range series.CoverPaths {
<img
src={ cover }
class={ "cover-img cover-" + fmt.Sprintf("%d", i) }
alt={ series.Name }
loading="lazy"
onerror="this.src='/static/placeholder-book.svg'"
/>
}
if len(series.CoverPaths) == 0 {
<div class="cover-img cover-0 flex items-center justify-center" style="background: var(--bg-primary); color: var(--text-secondary);">
@Icon("book", "h-8 w-8 opacity-60")
</div>
}
</div>
<div class="series-card-info px-3 py-2">
<h3 class="font-semibold text-sm line-clamp-2" style="color: var(--text-primary)">{ series.Name }</h3>
<p class="text-xs mt-1" style="color: var(--text-secondary)">
{ fmt.Sprintf("%d", series.BookCount) } of { fmt.Sprintf("%d", series.TotalInSeries) } books
</p>
</div>
</div>
</a>
}