Toolbar feedback round: the series search box now matches whatever the main search matches for a group — series NAME, any book's AUTHOR, and any book's TITLE inside the series (WHERE EXISTS per group-row, so counts stay true); the separate author input is gone from the toolbar (the author= param stays live for the JSON API and deep links). The sort control becomes a base-key select (Date added/Name/Author/Books/ Progress/Last read) plus a chevron direction toggle that flips and resubmits; sort/dir compose through ResolveSeriesSort (full registry keys keep working for back-compat, unknown base keys fall to recent). The search/apply button moved next to the search box as requested, and default URLs stay clean (sort/dir only emitted once the user chooses).
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { Alpine } from "./alpine";
|
|
import { initLibrarySwitcher } from "./library-switcher";
|
|
|
|
// Rendering ownership (AGENTS.md): the series grid, its paginator and
|
|
// its sort/filter toolbar are rendered by templates/series.templ. This
|
|
// page intentionally has NO TypeScript renderer — the old one here
|
|
// duplicated the templ markup via innerHTML and re-fetched at hardcoded
|
|
// page 1, stomping SSR pagination whenever the header's library restore
|
|
// fired. A library switch is a plain SSR navigation so the URL stays
|
|
// the single source of truth for library_id, page AND sort/filter state
|
|
// (the switch carries the current q/author/status/sort params along).
|
|
function navigateToSeries(libraryId: string): void {
|
|
const params = new URLSearchParams(window.location.search);
|
|
if (libraryId) {
|
|
params.set("library_id", libraryId);
|
|
} else {
|
|
params.delete("library_id");
|
|
}
|
|
params.set("page", "1");
|
|
window.location.href = `/series?${params.toString()}`;
|
|
}
|
|
|
|
Alpine.data("seriesPage", () => ({
|
|
initSeriesPage() {
|
|
initLibrarySwitcher({
|
|
onSwitch: navigateToSeries,
|
|
});
|
|
},
|
|
|
|
// flipSortDir inverts the direction hidden input and resubmits the
|
|
// plain-GET filter form (the URL stays the single source of truth).
|
|
flipSortDir() {
|
|
const input = this.$refs.sortDir as HTMLInputElement | undefined;
|
|
if (!input) return;
|
|
input.value = input.value === "asc" ? "desc" : "asc";
|
|
const form = input.closest("form") as HTMLFormElement | null;
|
|
if (form) form.requestSubmit();
|
|
},
|
|
}));
|