style: normalize code formatting in bookshelf.ts

- Convert indentation from 4 spaces to 2 spaces (matching project style)
- Standardize quotes to double quotes for consistency
- Reformat template literals for improved readability

This file contains the core bookshelf functionality including:
- Library selection and persistence
- Book rendering with cover images
- Pagination for large book collections
This commit is contained in:
2026-02-27 16:55:26 -05:00
parent 209e9f2a3c
commit 7bae42bb11
+79 -67
View File
@@ -1,113 +1,125 @@
function selectLibrary(libraryId: string): void { function selectLibrary(libraryId: string): void {
localStorage.setItem('selectedLibrary', libraryId); localStorage.setItem("selectedLibrary", libraryId);
document.querySelectorAll('.library-item').forEach(el => { document.querySelectorAll(".library-item").forEach((el) => {
el.classList.remove('ring-2'); el.classList.remove("ring-2");
el.classList.remove('ring-accent'); el.classList.remove("ring-accent");
}); });
const selected = document.querySelector(`[data-library-id="${libraryId}"]`); const selected = document.querySelector(`[data-library-id="${libraryId}"]`);
if (selected) { if (selected) {
selected.classList.add('ring-2'); selected.classList.add("ring-2");
selected.classList.add('ring-accent'); selected.classList.add("ring-accent");
} }
loadBookshelf(libraryId); loadBookshelf(libraryId);
} }
async function loadBookshelf(libraryId: string): Promise<void> { async function loadBookshelf(libraryId: string): Promise<void> {
const token = localStorage.getItem('token'); const token = localStorage.getItem("token");
if (!token) return; if (!token) return;
try { try {
const response = await fetch(`/api/libraries/${libraryId}/books`, { const response = await fetch(`/api/libraries/${libraryId}/books`, {
headers: { 'Authorization': `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` },
}); });
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
renderBooks(data.books || []); renderBooks(data.books || []);
}
} catch (error) {
console.error('Failed to load bookshelf:', error);
} }
} catch (error) {
console.error("Failed to load bookshelf:", error);
}
} }
function renderBooks(books: unknown[]): void { function renderBooks(books: unknown[]): void {
const container = document.getElementById('books-grid'); const container = document.getElementById("books-grid");
if (!container) return; if (!container) return;
if (books.length === 0) { if (books.length === 0) {
container.innerHTML = '<p class="text-center p-8" style="color: var(--text-secondary)">No books in this library</p>'; container.innerHTML =
return; '<p class="text-center p-8" style="color: var(--text-secondary)">No books in this library</p>';
} return;
}
container.innerHTML = books.map((book: any) => ` container.innerHTML = books
.map(
(book: any) => `
<div class="book-card p-3 rounded-lg border transition-transform hover:scale-105 cursor-pointer" <div class="book-card p-3 rounded-lg border transition-transform hover:scale-105 cursor-pointer"
style="background-color: var(--bg-secondary); border-color: var(--border)" style="background-color: var(--bg-secondary); border-color: var(--border)"
onclick="window.selectBook('${book.id}')"> onclick="window.selectBook('${book.id}')">
${book.cover_image_path ? ${
`<img src="/covers/${book.cover_image_path}" alt="${book.title}" class="w-full h-48 object-cover rounded mb-2">` : book.cover_image_path
`<div class="w-full h-48 rounded mb-2 flex items-center justify-center" style="background-color: var(--bg-primary)"> ? `<img src="${book.cover_image_path}" alt="${book.title}" class="w-full h-48 object-cover rounded mb-2">`
: `<div class="w-full h-48 rounded mb-2 flex items-center justify-center" style="background-color: var(--bg-primary)">
<span class="text-4xl">📖</span> <span class="text-4xl">📖</span>
</div>` </div>`
} }
<h3 class="font-medium text-sm truncate" style="color: var(--text-primary)">${book.title}</h3> <h3 class="font-medium text-sm truncate" style="color: var(--text-primary)">${book.title}</h3>
<p class="text-xs truncate" style="color: var(--text-secondary)">${book.author || 'Unknown Author'}</p> <p class="text-xs truncate" style="color: var(--text-secondary)">${book.author || "Unknown Author"}</p>
</div> </div>
`).join(''); `,
)
.join("");
} }
function selectBook(bookId: string): void { function selectBook(bookId: string): void {
localStorage.setItem('selectedBook', bookId); localStorage.setItem("selectedBook", bookId);
window.location.href = `/books/${bookId}`; window.location.href = `/books/${bookId}`;
} }
function changePage(page: number): void { function changePage(page: number): void {
const libraryId = localStorage.getItem('selectedLibrary'); const libraryId = localStorage.getItem("selectedLibrary");
if (!libraryId) return; if (!libraryId) return;
const offset = (page - 1) * 50; const offset = (page - 1) * 50;
loadBookshelfPaginated(libraryId, offset); loadBookshelfPaginated(libraryId, offset);
} }
async function loadBookshelfPaginated(libraryId: string, offset: number): Promise<void> { async function loadBookshelfPaginated(
const token = localStorage.getItem('token'); libraryId: string,
if (!token) return; offset: number,
): Promise<void> {
const token = localStorage.getItem("token");
if (!token) return;
try { try {
const response = await fetch(`/api/libraries/${libraryId}/books?offset=${offset}&limit=50`, { const response = await fetch(
headers: { 'Authorization': `Bearer ${token}` } `/api/libraries/${libraryId}/books?offset=${offset}&limit=50`,
}); {
headers: { Authorization: `Bearer ${token}` },
},
);
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
renderBooks(data.books || []); renderBooks(data.books || []);
updatePagination(data.total, offset); updatePagination(data.total, offset);
}
} catch (error) {
console.error('Failed to load bookshelf:', error);
} }
} catch (error) {
console.error("Failed to load bookshelf:", error);
}
} }
function updatePagination(total: number, offset: number): void { function updatePagination(total: number, offset: number): void {
const container = document.getElementById('pagination'); const container = document.getElementById("pagination");
if (!container) return; if (!container) return;
const limit = 50; const limit = 50;
const currentPage = Math.floor(offset / limit) + 1; const currentPage = Math.floor(offset / limit) + 1;
const totalPages = Math.ceil(total / limit); const totalPages = Math.ceil(total / limit);
if (totalPages <= 1) { if (totalPages <= 1) {
container.innerHTML = ''; container.innerHTML = "";
return; return;
} }
container.innerHTML = ` container.innerHTML = `
<div class="flex justify-center space-x-2"> <div class="flex justify-center space-x-2">
${currentPage > 1 ? `<button onclick="window.changePage(${currentPage - 1})" class="btn-secondary px-3 py-1 rounded">Previous</button>` : ''} ${currentPage > 1 ? `<button onclick="window.changePage(${currentPage - 1})" class="btn-secondary px-3 py-1 rounded">Previous</button>` : ""}
<span class="px-3 py-1" style="color: var(--text-secondary)">Page ${currentPage} of ${totalPages}</span> <span class="px-3 py-1" style="color: var(--text-secondary)">Page ${currentPage} of ${totalPages}</span>
${currentPage < totalPages ? `<button onclick="window.changePage(${currentPage + 1})" class="btn-secondary px-3 py-1 rounded">Next</button>` : ''} ${currentPage < totalPages ? `<button onclick="window.changePage(${currentPage + 1})" class="btn-secondary px-3 py-1 rounded">Next</button>` : ""}
</div> </div>
`; `;
} }