diff --git a/web/src/bookshelf.ts b/web/src/bookshelf.ts index 7a18891..bda72bb 100644 --- a/web/src/bookshelf.ts +++ b/web/src/bookshelf.ts @@ -41,7 +41,7 @@ Alpine.data("bookshelf", () => ({ this.showFiltersDropdown = !this.showFiltersDropdown; }, // Load a saved filter into the form - loadFilter(event: Event) { + async loadFilter(event: Event) { const button = event.target as HTMLElement; const filterRow = button.closest("[data-filter-id]"); if (!filterRow) return; @@ -50,10 +50,88 @@ Alpine.data("bookshelf", () => ({ if (!filterId) return; const filterName = button.textContent?.trim() || ""; - - // Note: Actual filter loading logic would go here - // For now, just show the filter name - showToast(`Filter: ${filterName}`, "success"); + + showToast(`Loading filter: ${filterName}...`, "info"); + + const token = localStorage.getItem("token"); + if (!token) { + showToast("Not authenticated", "error"); + return; + } + + try { + // Fetch filter details from API + const response = await fetch(`/api/saved-filters/${filterId}`, { + headers: { Authorization: `Bearer ${token}` }, + }); + + if (!response.ok) { + if (response.status === 404) { + showToast("Filter not found", "error"); + } else { + showToast("Failed to load filter", "error"); + } + return; + } + + const filter = await response.json(); + + // Parse filters JSON (string → object) + const filterData: Record = + typeof filter.filters === "string" + ? JSON.parse(filter.filters) + : filter.filters; + + // Get the hidden filter form + const filterForm = document.getElementById( + "filter-form", + ) as HTMLFormElement; + if (!filterForm) { + showToast("Filter form not found", "error"); + return; + } + + // Clear existing filter values + filterForm.innerHTML = ` + + + `; + + // Populate form fields from filter data + Object.entries(filterData).forEach(([key, value]) => { + if (value) { + // Only set non-empty values + const input = document.createElement("input"); + input.type = "hidden"; + input.name = key; + input.value = value; + filterForm.appendChild(input); + + // Also update visible form fields if they exist + const visibleField = document.querySelector( + `[name="${key}"]`, + ) as HTMLInputElement; + if (visibleField) { + visibleField.value = value; + } + } + }); + + // Trigger HTMX to apply the filter + // Use the first input to trigger the change event + const firstInput = filterForm.querySelector("input"); + if (firstInput) { + window.htmx.trigger(firstInput, "change"); + } + + showToast(`Filter applied: ${filterName}`, "success"); + + // Close the dropdown after applying + this.showFiltersDropdown = false; + } catch (error) { + console.error("Failed to load filter:", error); + showToast("Error loading filter", "error"); + } }, // Delete a saved filter async deleteFilter(event: Event) { @@ -105,7 +183,7 @@ Alpine.data("bookshelf", () => ({ showToast("Please enter a filter name", "error"); return; } - + // Collect filter form data const filterForm = document.getElementById( "filter-form", @@ -120,7 +198,7 @@ Alpine.data("bookshelf", () => ({ formData.forEach((value, key) => { filterData[key] = value.toString(); }); - + try { const response = await fetch("/api/saved-filters", { method: "POST", @@ -134,7 +212,7 @@ Alpine.data("bookshelf", () => ({ filters: filterData, }), }); - + if (response.ok) { showToast("Filter saved successfully", "success"); // Clear the filter name input @@ -155,13 +233,18 @@ Alpine.data("bookshelf", () => ({ function initBookshelf(): void { // Check if books were already rendered server-side const booksGrid = document.getElementById("books-grid"); - const hasServerBooks = booksGrid && booksGrid.querySelector('[data-book-id]') !== null; + const hasServerBooks = + booksGrid && booksGrid.querySelector("[data-book-id]") !== null; if (!hasServerBooks) { // Only trigger HTMX if no SSR books rendered - const librarySelect = document.getElementById("library-select") as HTMLSelectElement; + const librarySelect = document.getElementById( + "library-select", + ) as HTMLSelectElement; if (librarySelect && librarySelect.value) { - const filterForm = document.getElementById("filter-form") as HTMLFormElement; + const filterForm = document.getElementById( + "filter-form", + ) as HTMLFormElement; if (filterForm) { // Trigger initial HTMX load window.htmx.trigger(librarySelect, "change");