let allLocations = []; // To store fetched locations globally - ADDED HERE document.addEventListener('DOMContentLoaded', async () => { await fetchLocations(); // Fetch locations on page load const bookListContainer = document.getElementById('book-list-container'); const modal = document.getElementById('edit-modal'); const closeModalButton = modal.querySelector('.close-button'); const modalBookTitle = document.getElementById('modal-book-title'); const modalBookIdInput = document.getElementById('modal-book-id'); const modalSearchQueryInput = document.getElementById('modal-search-query'); const modalSearchButton = document.getElementById('modal-search-button'); const modalSearchResultsContainer = document.getElementById('modal-search-results'); const modalEditLocationSelect = document.getElementById('modal-edit-location'); const modalEditFields = { title: document.getElementById('modal-edit-title'), authors: document.getElementById('modal-edit-authors'), publishedDate: document.getElementById('modal-edit-publishedDate'), isbn: document.getElementById('modal-edit-isbn'), description: document.getElementById('modal-edit-description'), pages: document.getElementById('modal-edit-pages'), publishers: document.getElementById('modal-edit-publishers'), subjects: document.getElementById('modal-edit-subjects'), cover_small: document.getElementById('modal-edit-cover-small'), cover_medium: document.getElementById('modal-edit-cover-medium') }; const modalSaveButton = document.getElementById('modal-save-button'); let currentBooks = []; // To store the fetched books globally // let allLocations = []; // To store fetched locations globally - REMOVED FROM HERE let currentlyEditingBookId = null; const addNewBookButton = document.getElementById('add-new-book-button'); addNewBookButton.addEventListener('click', () => { currentlyEditingBookId = null; // Signal "add" mode modalBookIdInput.value = ''; // Clear hidden book ID input modalBookTitle.textContent = 'Add New Book'; // Update modal title for adding // Clear all form fields Object.values(modalEditFields).forEach(field => field.value = ''); modalEditLocationSelect.value = ''; // Reset location dropdown modalSearchResultsContainer.innerHTML = ''; // Clear any previous search results document.getElementById('modal-search-query').value = ''; // Clear search query too openModal(); // Open the modal for new entry }); // Authentication has been disabled for book updates // --- Fetch and Display Books --- async function fetchAndDisplayBooks() { try { const response = await fetch('/api/books'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } currentBooks = await response.json(); renderBookList(currentBooks); } catch (error) { console.error('Error fetching books:', error); bookListContainer.innerHTML = '
Error loading books. See console for details.
'; } } function renderBookList(books) { bookListContainer.innerHTML = ''; // Clear existing list if (books.length === 0) { bookListContainer.innerHTML = 'No books found in the library.
'; return; } const ul = document.createElement('ul'); ul.className = 'book-list'; // Add a class for styling if needed books.forEach(book => { const li = document.createElement('li'); const locationName = book.Location ? `${book.Location.name}${book.Location.shelf ? ' (Shelf: ' + book.Location.shelf + ')' : ''}` : 'No Location'; // Reverted to book.Location (capital L) li.innerHTML = `
Title: ${book.title || 'N/A'}
Author(s): ${book.authors || 'N/A'}
Published: ${book.publishedDate || 'N/A'}
ISBN: ${book.isbn || 'N/A'}
Publisher(s): ${book.publishers || 'N/A'}
Location: ${locationName}
Searching...
'; const searchButton = document.getElementById('modal-search-button'); if (searchButton) searchButton.disabled = true; let combinedResults = []; try { const googleQuery = isIsbnQuery ? `isbn:${searchQuery}` : searchQuery; const googleUrl = `https://www.googleapis.com/books/v1/volumes?q=${encodeURIComponent(googleQuery)}&maxResults=5`; const openLibFields = 'key,title,author_name,first_publish_year,isbn,cover_i,publisher,subject,number_of_pages_median,subtitle,first_sentence_value'; const openLibUrl = `https://openlibrary.org/search.json?q=${encodeURIComponent(searchQuery)}&limit=5&fields=${openLibFields}`; console.log("Searching Google Books API with URL:", googleUrl); console.log("Searching OpenLibrary API with URL:", openLibUrl); const [googleResult, openLibResult] = await Promise.allSettled([ fetch(googleUrl).then(res => res.ok ? res.json() : Promise.reject(new Error(`Google Books API request failed: ${res.status} ${res.statusText}`))), fetch(openLibUrl).then(res => res.ok ? res.json() : Promise.reject(new Error(`OpenLibrary API request failed: ${res.status} ${res.statusText}`))) ]); if (googleResult.status === 'fulfilled' && googleResult.value.items) { const googleBooks = googleResult.value.items.map(item => { const volumeInfo = item.volumeInfo; let isbn13 = '', isbn10 = ''; if (volumeInfo.industryIdentifiers) { volumeInfo.industryIdentifiers.forEach(id => { if (id.type === 'ISBN_13') isbn13 = id.identifier; if (id.type === 'ISBN_10') isbn10 = id.identifier; }); } return { title: volumeInfo.title, authors: volumeInfo.authors ? volumeInfo.authors.join(', ') : '', publishedDate: volumeInfo.publishedDate, isbn: isbn13 || isbn10, description: volumeInfo.description, pageCount: volumeInfo.pageCount, publishers: volumeInfo.publisher ? (Array.isArray(volumeInfo.publisher) ? volumeInfo.publisher.join(', ') : volumeInfo.publisher) : '', subjects: volumeInfo.categories ? volumeInfo.categories.join(', ') : '', cover_small: volumeInfo.imageLinks?.smallThumbnail, cover_medium: volumeInfo.imageLinks?.thumbnail, source: 'Google Books', rawData: volumeInfo }; }); combinedResults.push(...googleBooks); } else if (googleResult.status === 'rejected') { console.error('Error fetching from Google Books:', googleResult.reason); } if (openLibResult.status === 'fulfilled' && openLibResult.value.docs) { const openLibBooks = openLibResult.value.docs.map(doc => { return { title: doc.title, authors: doc.author_name ? doc.author_name.join(', ') : '', publishedDate: doc.first_publish_year ? String(doc.first_publish_year) : '', isbn: doc.isbn ? doc.isbn[0] : '', // Take first ISBN description: doc.first_sentence_value || doc.subtitle || '', pageCount: doc.number_of_pages_median, publishers: doc.publisher ? doc.publisher.join(', ') : '', subjects: doc.subject ? doc.subject.join(', ') : '', cover_small: doc.cover_i ? `https://covers.openlibrary.org/b/id/${doc.cover_i}-S.jpg` : '', cover_medium: doc.cover_i ? `https://covers.openlibrary.org/b/id/${doc.cover_i}-M.jpg` : '', source: 'OpenLibrary', rawData: doc }; }); combinedResults.push(...openLibBooks); } else if (openLibResult.status === 'rejected') { console.error('Error fetching from OpenLibrary:', openLibResult.reason); } displayModalSearchResults(combinedResults); } catch (error) { // Catch any unexpected errors during the setup or Promise.allSettled itself console.error('Error in handleModalSearch:', error); modalSearchResultsContainer.innerHTML = `An unexpected error occurred during search: ${error.message}. Please check console.
`; } finally { if (searchButton) searchButton.disabled = false; } } function displayModalSearchResults(items) { modalSearchResultsContainer.innerHTML = ''; if (!items || items.length === 0) { modalSearchResultsContainer.innerHTML = 'No results found from any source.
'; return; } const ul = document.createElement('ul'); items.forEach(bookItem => { const li = document.createElement('li'); li.innerHTML = ` ${bookItem.title || 'N/A'} by ${bookItem.authors || 'N/A'} (${bookItem.source})