diff --git a/templates/dashboard.templ b/templates/dashboard.templ
index 83fd37c..df75458 100644
--- a/templates/dashboard.templ
+++ b/templates/dashboard.templ
@@ -100,14 +100,94 @@ templ Dashboard(user User) {
+
+
@@ -370,11 +450,11 @@ templ Dashboard(user User) {
function filterMedia() {
const searchTerm = document.getElementById('search-input').value.toLowerCase();
- const filteredItems = mediaItems.filter(item =>
+ const filteredItems = mediaItems.filter(item =>
item.title.toLowerCase().includes(searchTerm) ||
(item.author && item.author.toLowerCase().includes(searchTerm))
);
-
+
// Temporarily replace mediaItems and re-render
const tempItems = mediaItems;
mediaItems = filteredItems;
@@ -382,15 +462,198 @@ templ Dashboard(user User) {
mediaItems = tempItems;
}
+ function applyFilters() {
+ const filters = {
+ author: document.getElementById('filter-author').value,
+ genre: document.getElementById('filter-genre').value,
+ series: document.getElementById('filter-series').value,
+ language: document.getElementById('filter-language').value,
+ yearMin: parseInt(document.getElementById('filter-year-min').value) || 0,
+ yearMax: parseInt(document.getElementById('filter-year-max').value) || 0,
+ hasCover: document.getElementById('filter-has-cover').checked
+ };
+
+ const sort = document.getElementById('sort-select').value;
+
+ // Update URL for shareability
+ const params = new URLSearchParams();
+ params.set('library_id', currentLibrary.id);
+ params.set('sort', sort);
+ Object.entries(filters).forEach(([key, value]) => {
+ if (value && value !== 0) {
+ if (key === 'hasCover') {
+ if (value === true) params.set(`has_cover`, 'true');
+ } else {
+ params.set(`${key}_filter`, value);
+ }
+ }
+ });
+
+ window.history.pushState({}, '', `?${params.toString()}`);
+
+ loadMediaItemsWithFilters(filters, sort);
+ displayActiveFilters(filters);
+ }
+
+ function loadMediaItemsWithFilters(filters, sort) {
+ if (!currentLibrary) return;
+
+ const loading = document.getElementById('loading');
+ const container = document.getElementById('media-container');
+
+ loading.style.display = 'block';
+ container.innerHTML = '';
+
+ const params = new URLSearchParams();
+ params.set('library_id', currentLibrary.id);
+ params.set('sort', sort);
+ params.set('limit', 50);
+ params.set('offset', 0);
+
+ // Only add filter params if they have values
+ if (filters.author) params.set('author_filter', filters.author);
+ if (filters.series) params.set('series_filter', filters.series);
+ if (filters.genre) params.set('genre_filter', filters.genre);
+ if (filters.language) params.set('language_filter', filters.language);
+ if (filters.yearMin) params.set('year_min', filters.yearMin);
+ if (filters.yearMax) params.set('year_max', filters.yearMax);
+ if (filters.hasCover) params.set('has_cover', 'true');
+
+ fetch(`/api/media-items/filtered?${params.toString()}`, {
+ headers: {
+ 'Authorization': 'Bearer ' + localStorage.getItem('token'),
+ 'Content-Type': 'application/json'
+ }
+ })
+ .then(response => response.json())
+ .then(data => {
+ loading.style.display = 'none';
+ mediaItems = data.data || [];
+ renderMediaItems();
+ })
+ .catch(error => {
+ loading.style.display = 'none';
+ console.error('Error loading filtered media items:', error);
+ container.innerHTML = '
Error loading media items. Please try again.
';
+ });
+ }
+
+ function displayActiveFilters(filters) {
+ const container = document.getElementById('active-filters');
+ const chipsContainer = document.getElementById('active-filters-container');
+ chipsContainer.innerHTML = '';
+
+ let hasFilters = false;
+
+ const filterLabels = {
+ author: 'Author',
+ genre: 'Genre',
+ series: 'Series',
+ language: 'Language',
+ yearMin: 'Year From',
+ yearMax: 'Year To',
+ hasCover: 'Has Cover'
+ };
+
+ Object.entries(filters).forEach(([key, value]) => {
+ if (value && value !== 0) {
+ hasFilters = true;
+ const label = filterLabels[key] || key;
+ const displayValue = key === 'hasCover' ? 'Yes' : value;
+
+ const chip = document.createElement('span');
+ chip.className = 'px-3 py-1 rounded-full text-sm flex items-center gap-2 cursor-pointer';
+ chip.style.cssText = 'background-color: var(--accent); color: var(--bg-primary)';
+ chip.innerHTML = `${label}: ${displayValue}
`;
+ chip.onclick = () => clearFilter(key);
+ chipsContainer.appendChild(chip);
+ }
+ });
+
+ container.classList.toggle('hidden', !hasFilters);
+ }
+
+ function clearFilter(filterKey) {
+ switch (filterKey) {
+ case 'author':
+ document.getElementById('filter-author').value = '';
+ break;
+ case 'genre':
+ document.getElementById('filter-genre').value = '';
+ break;
+ case 'series':
+ document.getElementById('filter-series').value = '';
+ break;
+ case 'language':
+ document.getElementById('filter-language').value = '';
+ break;
+ case 'yearMin':
+ document.getElementById('filter-year-min').value = '';
+ break;
+ case 'yearMax':
+ document.getElementById('filter-year-max').value = '';
+ break;
+ case 'hasCover':
+ document.getElementById('filter-has-cover').checked = false;
+ break;
+ }
+ applyFilters();
+ }
+
+ function clearFilters() {
+ document.getElementById('filter-author').value = '';
+ document.getElementById('filter-genre').value = '';
+ document.getElementById('filter-series').value = '';
+ document.getElementById('filter-language').value = '';
+ document.getElementById('filter-year-min').value = '';
+ document.getElementById('filter-year-max').value = '';
+ document.getElementById('filter-has-cover').checked = false;
+
+ // Clear URL params
+ const params = new URLSearchParams();
+ params.set('library_id', currentLibrary.id);
+ window.history.pushState({}, '', `?${params.toString()}`);
+
+ loadMediaItems();
+ document.getElementById('active-filters').classList.add('hidden');
+ }
+
function viewMediaItem(mediaId) {
// TODO: Implement detailed media view
alert('Media viewer coming soon!');
}
- // Load libraries on page load
+ // Load filters from URL on page load
document.addEventListener('DOMContentLoaded', function() {
loadTheme();
loadLibraries();
+
+ // Restore filters from URL
+ const params = new URLSearchParams(window.location.search);
+ if (params.has('author_filter')) {
+ document.getElementById('filter-author').value = params.get('author_filter');
+ }
+ if (params.has('genre_filter')) {
+ document.getElementById('filter-genre').value = params.get('genre_filter');
+ }
+ if (params.has('series_filter')) {
+ document.getElementById('filter-series').value = params.get('series_filter');
+ }
+ if (params.has('language_filter')) {
+ document.getElementById('filter-language').value = params.get('language_filter');
+ }
+ if (params.has('year_min')) {
+ document.getElementById('filter-year-min').value = params.get('year_min');
+ }
+ if (params.has('year_max')) {
+ document.getElementById('filter-year-max').value = params.get('year_max');
+ }
+ if (params.has('has_cover')) {
+ document.getElementById('filter-has-cover').checked = params.get('has_cover') === 'true';
+ }
+ if (params.has('sort')) {
+ document.getElementById('sort-select').value = params.get('sort');
+ }
});
Header(user, \"/dashboard\")