// Bookshelf functionality - procedural/imperative style import { Alpine } from "./alpine"; import { showToast } from "./toast"; function clearFilters(): void { const filterForm = document.getElementById("filter-form") as HTMLFormElement; if (!filterForm) return; // Reset all form fields const inputs = filterForm.querySelectorAll("input, select"); inputs.forEach((input) => { if (input instanceof HTMLInputElement && input.type === "checkbox") { input.checked = false; } else { (input as HTMLInputElement).value = ""; } }); // Trigger HTMX reload with cleared filters window.htmx.trigger(filterForm, "change"); } // Alpine.js component Alpine.data("bookshelf", () => ({ // Component state showSaveModal: false, filterName: "", showFiltersDropdown: false, // Standalone function references (don't access component state) clearFilters, initBookshelf, // Inline method - opens the modal showSaveFilterModal() { this.showSaveModal = true; }, // Toggle the filters dropdown toggleFiltersDropdown() { this.showFiltersDropdown = !this.showFiltersDropdown; }, // Load a saved filter into the form loadFilter(event: Event) { const button = event.target as HTMLElement; const filterRow = button.closest("[data-filter-id]"); if (!filterRow) return; const filterId = filterRow?.getAttribute("data-filter-id"); 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"); }, // Delete a saved filter async deleteFilter(event: Event) { const button = event.target as HTMLElement; const filterRow = button.closest("[data-filter-id]"); if (!filterRow) return; const filterId = filterRow?.getAttribute("data-filter-id"); if (!filterId) return; if (!confirm("Are you sure you want to delete this filter?")) return; const token = localStorage.getItem("token"); if (!token) { showToast("Not authenticated", "error"); return; } try { const response = await fetch(`/api/saved-filters/${filterId}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` }, }); if (response.ok) { showToast("Filter deleted", "success"); // Remove the element from DOM filterRow?.remove(); } else { showToast("Failed to delete filter", "error"); } } catch (error) { console.error("Failed to delete filter:", error); showToast("Error deleting filter", "error"); } }, // Inline method - saves the filter and closes modal async saveFilter(event: Event) { event.preventDefault(); const token = localStorage.getItem("token"); if (!token) { showToast("Not authenticated", "error"); return; } // Get filter name from component state const filterName = this.filterName; if (!filterName) { showToast("Please enter a filter name", "error"); return; } // Collect filter form data const filterForm = document.getElementById( "filter-form", ) as HTMLFormElement; if (!filterForm) { showToast("Filter form not found", "error"); return; } const formData = new FormData(filterForm); const filterData: Record = {}; formData.forEach((value, key) => { filterData[key] = value.toString(); }); try { const response = await fetch("/api/saved-filters", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ name: filterName, resource_type: "media-items", filters: filterData, }), }); if (response.ok) { showToast("Filter saved successfully", "success"); // Clear the filter name input this.filterName = ""; // Close the modal this.showSaveModal = false; } else { showToast("Failed to save filter", "error"); } } catch (error) { console.error("Failed to save filter:", error); showToast("Error saving filter", "error"); } }, })); // Standalone function - initialize the bookshelf (NOT async, like dashboard.ts) 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; if (!hasServerBooks) { // Only trigger HTMX if no SSR books rendered const librarySelect = document.getElementById("library-select") as HTMLSelectElement; if (librarySelect && librarySelect.value) { const filterForm = document.getElementById("filter-form") as HTMLFormElement; if (filterForm) { // Trigger initial HTMX load window.htmx.trigger(librarySelect, "change"); } } } } export { clearFilters };