feat: update bookshelf template with unified search UI

- Change search box to use /api/media-items/search endpoint (was /filtered)
- Add autocomplete to all 4 text filters: author, genre, series, language
- Add series and language filters (were missing)
- Add datalist elements for autocomplete dropdowns
- Change filter triggers to Enter key instead of instant search
- Preserve existing sort dropdown (all 5 options: title ASC/DESC, author ASC/DESC, created_at ASC/DESC, page_count ASC/DESC)
- Preserve Save Filter button and modal
- Preserve Load Filter button and dropdown
- Preserve Clear Filters button
- Update pagination to use /search endpoint
- Add Alpine.js event handlers for dropdown population (@input.debounce.300ms)

All filter inputs include hidden filter-form via hx-include for combined searches.
This commit is contained in:
john-okeefe committed 2026-03-23 22:37:58 -04:00
1 parent 172536f888
commit 2e24ce00cf
2 files changed
+77 -42

No files matched your search

+68 -33
View File
@@ -75,40 +75,32 @@ templ BookShelf(
type="text"
placeholder="Search all fields..."
hx-get="/api/media-items/search"
hx-trigger="keyup[key=='Enter'] from:#search-form, keyup changed delay:500ms"
hx-trigger="keyup[key=='Enter'] from:#filter-form, keyup changed delay:500ms"
hx-target="#books-grid"
hx-include="#filter-form, #library-select"
/>
</div>
<!-- Author Filter -->
<!-- Author Filter with Autocomplete -->
<div class="flex-1 min-w-[150px]">
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
Author
</label>
<div class="relative" x-data="{ authorValues: [] }">
<input
type="text"
name="author_filter"
placeholder="Filter by author"
class="w-full px-3 py-2 border rounded-lg"
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="change"
hx-include="#filter-form"
list="author-datalist"
@focus="fetchAuthorValues($el)"
@input.debounce.300ms="if($el.value === '') authorValues = []"
/>
<datalist id="author-datalist">
<template x-for="item in authorValues" :key="item.value">
<option :value="item.value" x-text="`${item.value} (${item.count})`"></option>
</template>
</datalist>
</div>
<input
type="text"
name="author_filter"
placeholder="Filter by author"
class="w-full px-3 py-2 border rounded-lg"
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
list="author-datalist"
@input.debounce.300ms="if($el.value.length >= 2) fetchAuthorValues($el)"
/>
<datalist id="author-datalist"></datalist>
</div>
<!-- Genre Filter -->
<!-- Genre Filter with Autocomplete -->
<div class="flex-1 min-w-[150px]">
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
Genre
@@ -121,9 +113,52 @@ templ BookShelf(
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="change"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
list="genre-datalist"
@input.debounce.300ms="if($el.value.length >= 2) fetchGenreValues($el)"
/>
<datalist id="genre-datalist"></datalist>
</div>
<!-- Series Filter with Autocomplete (NEW) -->
<div class="flex-1 min-w-[150px]">
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
Series
</label>
<input
type="text"
name="series_filter"
placeholder="Filter by series"
class="w-full px-3 py-2 border rounded-lg"
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
list="series-datalist"
@input.debounce.300ms="if($el.value.length >= 2) fetchSeriesValues($el)"
/>
<datalist id="series-datalist"></datalist>
</div>
<!-- Language Filter with Autocomplete (NEW) -->
<div class="flex-1 min-w-[150px]">
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
Language
</label>
<input
type="text"
name="language_filter"
placeholder="Filter by language"
class="w-full px-3 py-2 border rounded-lg"
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
list="language-datalist"
@input.debounce.300ms="if($el.value.length >= 2) fetchLanguageValues($el)"
/>
<datalist id="language-datalist"></datalist>
</div>
<!-- Year Range -->
<div class="flex-1 min-w-[200px]">
@@ -139,7 +174,7 @@ templ BookShelf(
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="change"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
/>
<input
@@ -150,7 +185,7 @@ templ BookShelf(
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
hx-get="/api/media-items/search"
hx-target="#books-grid"
hx-trigger="change"
hx-trigger="keyup[key=='Enter'] from:#filter-form"
hx-include="#filter-form"
/>
</div>
@@ -171,7 +206,7 @@ templ BookShelf(
<span class="text-sm" style="color: var(--text-primary)">Has Cover</span>
</label>
</div>
<!-- Sort -->
<!-- Sort By Dropdown (PRESERVED) -->
<div class="flex-1 min-w-[150px]">
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">
Sort By
@@ -192,7 +227,7 @@ templ BookShelf(
<option value="page_count DESC">Page Count</option>
</select>
</div>
<!-- Save Filter Button -->
<!-- Save Filter Button (PRESERVED) -->
<div class="flex items-end">
<button
@click="showSaveFilterModal()"
@@ -202,7 +237,7 @@ templ BookShelf(
💾 Save Filter
</button>
</div>
<!-- Load Filter Button -->
<!-- Load Filter Button (PRESERVED) -->
<div class="flex items-end relative">
<button
@click="toggleFiltersDropdown()"
@@ -211,7 +246,7 @@ templ BookShelf(
>
📂 Load Filter
</button>
<!-- Saved Filters Dropdown -->
<!-- Saved Filters Dropdown (PRESERVED) -->
<div
x-show="showFiltersDropdown"
@click.outside="showFiltersDropdown = false"
@@ -249,7 +284,7 @@ templ BookShelf(
</div>
</div>
</div>
<!-- Clear Filters -->
<!-- Clear Filters Button (PRESERVED) -->
<div class="flex items-end">
<button
@click="clearFilters()"
@@ -260,7 +295,7 @@ templ BookShelf(
</button>
</div>
</div>
<!-- Hidden form for HTMX include -->
<!-- Hidden form for HTMX include (PRESERVED) -->
<form id="filter-form" class="hidden">
<input type="hidden" name="limit" value="50"/>
<input type="hidden" name="offset" value="0"/>
+9 -9
View File
@@ -52,7 +52,7 @@ func BookShelf(
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"w-full px-4 sm:px-6 lg:px-8 py-8\"><!-- Filter Bar --><div class=\"mb-6 card p-4 rounded-lg border\" style=\"background-color: var(--bg-secondary); border-color: var(--border);\"><div class=\"flex flex-wrap gap-4 items-center\"><!-- Library Selector --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Library</label> <select id=\"library-select\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"w-full px-4 sm:px-6 lg:px-8 py-8\"><!-- Filter Bar --><div class=\"mb-6 card p-4 rounded-lg border\" style=\"background-color: var(--bg-secondary); border-color: var(--border);\"><div class=\"flex flex-wrap gap-4 items-center\"><!-- Library Selector --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Library</label> <select id=\"library-select\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -128,7 +128,7 @@ func BookShelf(
}
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div><!-- Search Input --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Search</label> <input type=\"text\" name=\"search\" placeholder=\"Search title, author...\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"keyup changed delay:300ms\" hx-include=\"#filter-form\"></div><!-- Author Filter --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Author</label> <input type=\"text\" name=\"author_filter\" placeholder=\"Filter by author\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"></div><!-- Series Filter --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Series</label> <input type=\"text\" name=\"series_filter\" placeholder=\"Filter by series\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"></div><!-- Genre Filter --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Genre</label> <input type=\"text\" name=\"genre_filter\" placeholder=\"Filter by genre\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"></div><!-- Year Range --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Year Range</label><div class=\"flex gap-2\"><input type=\"number\" name=\"year_min\" placeholder=\"From\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"> <input type=\"number\" name=\"year_max\" placeholder=\"To\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"></div></div><!-- Has Cover Filter --><div class=\"flex items-end\"><label class=\"flex items-center gap-2 cursor-pointer\"><input type=\"checkbox\" name=\"has_cover\" value=\"true\" class=\"w-4 h-4 rounded\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"> <span class=\"text-sm\" style=\"color: var(--text-primary)\">Has Cover</span></label></div><!-- Sort --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Sort By</label> <select name=\"sort\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/filtered\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"><option value=\"title ASC\">Title (A-Z)</option> <option value=\"title DESC\">Title (Z-A)</option> <option value=\"author ASC\">Author (A-Z)</option> <option value=\"created_at DESC\">Date Added</option> <option value=\"page_count DESC\">Page Count</option></select></div><!-- Save Filter Button --><div class=\"flex items-end\"><button @click=\"showSaveFilterModal()\" class=\"px-4 py-2 rounded-lg font-medium\" style=\"background-color: var(--accent); color: var(--bg-primary);\">💾 Save Filter</button></div><!-- Load Filter Button --><div class=\"flex items-end relative\"><button @click=\"toggleFiltersDropdown()\" class=\"px-4 py-2 rounded-lg font-medium border\" style=\"border-color: var(--border); color: var(--text-primary);\">📂 Load Filter</button><!-- Saved Filters Dropdown --><div x-show=\"showFiltersDropdown\" @click.outside=\"showFiltersDropdown = false\" x-transition:enter=\"transition ease-out duration-200\" x-transition:enter-start=\"opacity-0 scale-95\" x-transition:enter-end=\"opacity-100 scale-100\" x-transition:leave=\"transition ease-in duration-150\" x-transition:leave-start=\"opacity-100 scale-100\" x-transition:leave-end=\"opacity-0 scale-95\" class=\"aLine truncated
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div><!-- Search Input --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Search</label> <input name=\"q\" type=\"text\" placeholder=\"Search all fields...\" hx-get=\"/api/media-items/search\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form, keyup changed delay:500ms\" hx-target=\"#books-grid\" hx-include=\"#filter-form, #library-select\"></div><!-- Author Filter with Autocomplete --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Author</label> <input type=\"text\" name=\"author_filter\" placeholder=\"Filter by author\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\" list=\"author-datalist\" @input.debounce.300ms=\"if($el.value.length >= 2) fetchAuthorValues($el)\"> <datalist id=\"author-datalist\"></datalist></div><!-- Genre Filter with Autocomplete --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Genre</label> <input type=\"text\" name=\"genre_filter\" placeholder=\"Filter by genre\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\" list=\"genre-datalist\" @input.debounce.300ms=\"if($el.value.length >= 2) fetchGenreValues($el)\"> <datalist id=\"genre-datalist\"></datalist></div><!-- Series Filter with Autocomplete (NEW) --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Series</label> <input type=\"text\" name=\"series_filter\" placeholder=\"Filter by series\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\" list=\"series-datalist\" @input.debounce.300ms=\"if($el.value.length >= 2) fetchSeriesValues($el)\"> <datalist id=\"series-datalist\"></datalist></div><!-- Language Filter with Autocomplete (NEW) --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Language</label> <input type=\"text\" name=\"language_filter\" placeholder=\"Filter by language\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\" list=\"language-datalist\" @input.debounce.300ms=\"if($el.value.length >= 2) fetchLanguageValues($el)\"> <datalist id=\"language-datalist\"></datalist></div><!-- Year Range --><div class=\"flex-1 min-w-[200px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Year Range</label><div class=\"flex gap-2\"><input type=\"number\" name=\"year_min\" placeholder=\"From\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\"> <input type=\"number\" name=\"year_max\" placeholder=\"To\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"keyup[key=='Enter'] from:#filter-form\" hx-include=\"#filter-form\"></div></div><!-- Has Cover Filter --><div class=\"flex items-end\"><label class=\"flex items-center gap-2 cursor-pointer\"><input type=\"checkbox\" name=\"has_cover\" value=\"true\" class=\"w-4 h-4 rounded\" hx-get=\"/api/media-items/search\" hx-target=\"#books-grid\" hx-trigger=\"change\" hx-include=\"#filter-form\"> <span class=\"text-sm\" style=\"color: var(--text-primary)\">Has Cover</span></label></div><!-- Sort By Dropdown (PRESERVED) --><div class=\"flex-1 min-w-[150px]\"><label class=\"block text-sm font-medium mb-2\" style=\"color: var(--text-secondary)\">Sort By</label> <select name=\"sort\" class=\"w-full px-3 py-2 border rounded-lg\" style=\"background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);\" hx-get=\"/api/media-items/searchLine truncated
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -140,7 +140,7 @@ func BookShelf(
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(uuidToString(filter.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 243, Col: 172}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 270, Col: 172}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -153,7 +153,7 @@ func BookShelf(
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(filter.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 245, Col: 26}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 272, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -174,7 +174,7 @@ func BookShelf(
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div></div></div><!-- Clear Filters --><div class=\"flex items-end\"><button @click=\"clearFilters()\" class=\"px-4 py-2 rounded-lg font-medium border\" style=\"border-color: var(--border); color: var(--text-primary);\">✕ Clear</button></div></div><!-- Hidden form for HTMX include --><form id=\"filter-form\" class=\"hidden\"><input type=\"hidden\" name=\"limit\" value=\"50\"> <input type=\"hidden\" name=\"offset\" value=\"0\"></form></div><!-- Books Grid --><div id=\"books-grid\" class=\"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div></div></div><!-- Clear Filters Button (PRESERVED) --><div class=\"flex items-end\"><button @click=\"clearFilters()\" class=\"px-4 py-2 rounded-lg font-medium border\" style=\"border-color: var(--border); color: var(--text-primary);\">✕ Clear</button></div></div><!-- Hidden form for HTMX include (PRESERVED) --><form id=\"filter-form\" class=\"hidden\"><input type=\"hidden\" name=\"limit\" value=\"50\"> <input type=\"hidden\" name=\"offset\" value=\"0\"></form></div><!-- Books Grid --><div id=\"books-grid\" class=\"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -196,7 +196,7 @@ func BookShelf(
return templ_7745c5c3_Err
}
if count > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<button type=\"button\" class=\"px-4 py-2 rounded-lg border disabled:opacity-50\" style=\"border-color: var(--border); color: var(--text-primary);\" hx-get=\"/api/media-items/filtered?library_id={ currentLibraryID }&limit={ limit }&offset={ offset - limit }\" hx-target=\"#books-grid\" hx-include=\"#filter-form\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<button type=\"button\" class=\"px-4 py-2 rounded-lg border disabled:opacity-50\" style=\"border-color: var(--border); color: var(--text-primary);\" hx-get=\"/api/media-items/search?library_id={ currentLibraryID }&limit={ limit }&offset={ offset - limit }\" hx-target=\"#books-grid\" hx-include=\"#filter-form\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -213,13 +213,13 @@ func BookShelf(
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(offset/limit + 1)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 306, Col: 32}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 333, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</span> <button class=\"px-4 py-2 rounded-lg border disabled:opacity-50\" style=\"border-color: var(--border); color: var(--text-primary);\" hx-get=\"/api/media-items/filtered?library_id={ currentLibraryID }&limit={ limit }&offset={ offset + limit }\" hx-target=\"#books-grid\" hx-include=\"#filter-form\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</span> <button class=\"px-4 py-2 rounded-lg border disabled:opacity-50\" style=\"border-color: var(--border); color: var(--text-primary);\" hx-get=\"/api/media-items/search?library_id={ currentLibraryID }&limit={ limit }&offset={ offset + limit }\" hx-target=\"#books-grid\" hx-include=\"#filter-form\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -246,7 +246,7 @@ func BookShelf(
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(errorMessage)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 323, Col: 58}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 350, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {