fix(dashboard): use anchor tags for client-side rendered book cards
When switching libraries via TypeScript, renderBookCard() built book
cards as <div> elements with data-action="view-book" for event
delegation, but the click handler was commented out — making books
unclickable after any library switch. The SSR path used proper <a> tags.
Now renderBookCard() wraps cards in <a href="/media/{id}"> to match the
SSR BookCard template, so book links work identically regardless of
whether content was server-rendered or client-rendered.
Also removed the dead view-book handler code and viewBook() stub.
Additionally fixed a listener re-registration bug where the input and
library-select change listeners were nested inside the click callback,
causing them to be registered N times after N clicks. Moved them to
initDashboard() scope so they register exactly once.
This commit is contained in:
+26
-33
@@ -326,10 +326,9 @@ function renderBookCard(book: BookInfo): string {
|
||||
const coverUrl = book.cover_image_path || "/static/placeholder-book.svg";
|
||||
|
||||
return `
|
||||
<a href="/media/${book.media_item_id}">
|
||||
<div class="book-card flex-shrink-0 w-36 rounded-lg overflow-hidden snap-start cursor-pointer
|
||||
transition-transform duration-200 hover:scale-105"
|
||||
data-action="view-book"
|
||||
data-book-id="${book.media_item_id}"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
aria-label="View ${book.title}">
|
||||
@@ -348,12 +347,10 @@ function renderBookCard(book: BookInfo): string {
|
||||
${book.author ? `<p class="text-sm line-clamp-1" style="color: var(--text-secondary)">${book.author}</p>` : ""}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
// function viewBook(bookId: string): void {
|
||||
// console.log("View book:", bookId);
|
||||
// }
|
||||
|
||||
async function reloadPage(): Promise<void> {
|
||||
//Get current library from dropdown
|
||||
@@ -468,11 +465,6 @@ function initDashboard() {
|
||||
break;
|
||||
}
|
||||
|
||||
// case "view-book": {
|
||||
// const bookId = target.dataset.bookId || actionElem?.dataset.bookId;
|
||||
// if (bookId) viewBook(bookId);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case "reload-page":
|
||||
reloadPage();
|
||||
@@ -485,33 +477,34 @@ function initDashboard() {
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("input", (e: Event) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const actionElem = target.closest("[data-input-action]") as HTMLElement;
|
||||
const action = actionElem?.getAttribute("data-input-action");
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case "update-items-count": {
|
||||
const input = target as HTMLInputElement;
|
||||
const displayTarget = input.getAttribute("target");
|
||||
if (displayTarget) updateItemsCount(input, displayTarget);
|
||||
break;
|
||||
}
|
||||
document.addEventListener("input", (e: Event) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const actionElem = target.closest("[data-input-action]") as HTMLElement;
|
||||
const action = actionElem?.getAttribute("data-input-action");
|
||||
|
||||
switch (action) {
|
||||
case "update-items-count": {
|
||||
const input = target as HTMLInputElement;
|
||||
const displayTarget = input.getAttribute("target");
|
||||
if (displayTarget) updateItemsCount(input, displayTarget);
|
||||
break;
|
||||
}
|
||||
});
|
||||
// Load saved library on page load
|
||||
const librarySelect = document.getElementById(
|
||||
"library-select",
|
||||
) as HTMLSelectElement;
|
||||
if (librarySelect) {
|
||||
librarySelect.addEventListener("change", (e) => {
|
||||
const target = e.target as HTMLSelectElement;
|
||||
if (target.value) {
|
||||
switchLibrary(target.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const librarySelect = document.getElementById(
|
||||
"library-select",
|
||||
) as HTMLSelectElement;
|
||||
if (librarySelect) {
|
||||
librarySelect.addEventListener("change", (e) => {
|
||||
const target = e.target as HTMLSelectElement;
|
||||
if (target.value) {
|
||||
switchLibrary(target.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { initDashboard };
|
||||
|
||||
Reference in New Issue
Block a user