feat: Add clear filters functionality and improve product filter options in dashboard
This commit is contained in:
+43
-12
@@ -86,6 +86,9 @@ function initEventListeners() {
|
||||
}
|
||||
});
|
||||
|
||||
// Clear filters button
|
||||
document.getElementById('clearFiltersBtn')?.addEventListener('click', clearAllFilters);
|
||||
|
||||
// Add favorite button
|
||||
document.getElementById('addFavoriteBtn')?.addEventListener('click', addFavorite);
|
||||
|
||||
@@ -96,6 +99,16 @@ function initEventListeners() {
|
||||
});
|
||||
}
|
||||
|
||||
// Clear all product filters
|
||||
function clearAllFilters() {
|
||||
document.getElementById('filterSite').value = '';
|
||||
document.getElementById('filterCategory').value = '';
|
||||
document.getElementById('filterStock').value = '';
|
||||
document.getElementById('filterFavorites').checked = false;
|
||||
currentEventFilter = null;
|
||||
loadProducts();
|
||||
}
|
||||
|
||||
// API Helpers
|
||||
async function api(endpoint, options = {}) {
|
||||
try {
|
||||
@@ -328,23 +341,23 @@ async function loadProducts() {
|
||||
const cleanName = cleanProductName(product.name);
|
||||
const hasImage = product.image_url && !product.image_url.includes('data:') && product.image_url.length > 10;
|
||||
|
||||
// Build store logo fallback HTML
|
||||
const storeLogoHtml = `
|
||||
<div class="product-store-icon" style="background:${storeInfo.bgColor};">
|
||||
<img src="${storeInfo.logo}" alt="${storeInfo.name}" class="product-store-logo"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<span class="product-store-fallback" style="display:none; color:${storeInfo.color};">${storeInfo.fallback}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return `
|
||||
<div class="product-card ${product.in_stock ? 'in-stock' : 'out-of-stock'} ${product.is_favorite ? 'favorite' : ''}"
|
||||
onclick="showProductDetails(${product.id})">
|
||||
<div class="product-image-container">
|
||||
${hasImage
|
||||
? `<img src="${product.image_url}" class="product-image" alt="" onerror="this.outerHTML=\`${storeLogoHtml.replace(/`/g, '\\`').replace(/\n/g, '')}\`">`
|
||||
: storeLogoHtml
|
||||
? `<img src="${product.image_url}" class="product-image" alt="" onerror="handleProductImageError(this, '${product.site}')">`
|
||||
: `<div class="product-store-icon" style="background:${storeInfo.bgColor};">
|
||||
<img src="${storeInfo.logo}" alt="${storeInfo.name}" class="product-store-logo"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<span class="product-store-fallback" style="display:none; color:${storeInfo.color};">${storeInfo.fallback}</span>
|
||||
</div>`
|
||||
}
|
||||
<div class="product-store-badge" style="background:${storeInfo.bgColor};">
|
||||
<img src="${storeInfo.logo}" alt="${storeInfo.name}" class="store-badge-logo"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<span class="store-badge-fallback" style="display:none; color:${storeInfo.color};">${storeInfo.fallback}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-name">${cleanName}</div>
|
||||
<div class="product-meta">
|
||||
@@ -356,7 +369,7 @@ async function loadProducts() {
|
||||
<div class="product-actions">
|
||||
<span class="product-site">${storeInfo.name}</span>
|
||||
<button class="btn-favorite ${product.is_favorite ? 'active' : ''}"
|
||||
onclick="event.stopPropagation(); toggleFavorite('${product.url}', '${cleanName}', ${product.favorite_id || 'null'})">
|
||||
onclick="event.stopPropagation(); toggleFavorite('${product.url}', '${cleanName.replace(/'/g, "\\'")}', ${product.favorite_id || 'null'})">
|
||||
${product.is_favorite ? '★' : '☆'}
|
||||
</button>
|
||||
</div>
|
||||
@@ -365,6 +378,24 @@ async function loadProducts() {
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// Handle product image errors by showing store icon
|
||||
function handleProductImageError(img, site) {
|
||||
const storeInfo = STORE_INFO[site] || { name: site, color: '#333', bgColor: '#666', logo: '', fallback: '?' };
|
||||
const container = img.parentElement;
|
||||
img.style.display = 'none';
|
||||
|
||||
// Create fallback element
|
||||
const fallback = document.createElement('div');
|
||||
fallback.className = 'product-store-icon';
|
||||
fallback.style.background = storeInfo.bgColor;
|
||||
fallback.innerHTML = `
|
||||
<img src="${storeInfo.logo}" alt="${storeInfo.name}" class="product-store-logo"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<span class="product-store-fallback" style="display:none; color:${storeInfo.color};">${storeInfo.fallback}</span>
|
||||
`;
|
||||
container.insertBefore(fallback, img);
|
||||
}
|
||||
|
||||
async function showProductDetails(productId) {
|
||||
const product = await api(`/products/${productId}`);
|
||||
const history = await api(`/products/${productId}/history`);
|
||||
|
||||
Reference in New Issue
Block a user