document.addEventListener('DOMContentLoaded', () => {
const productGrid = document.getElementById('product-grid');
const loader = document.getElementById('loader');
let products = [];
// Cart State
let cartCount = 0;
// --- Event Listeners for Filters ---
document.getElementById('filter-all').addEventListener('click', () => filterProducts('all'));
document.getElementById('filter-tech').addEventListener('click', () => filterProducts('tech'));
document.getElementById('filter-design').addEventListener('click', () => filterProducts('design'));
// --- Function: Fetch Data ---
async function loadProducts() {
// Show Loader
loader.style.display = 'flex';
productGrid.innerHTML = '';
try {
// Attempt to fetch from local data.json file
const response = await fetch('data.json');
if (!response.ok) throw new Error("HTTP error");
products = await response.json();
} catch (error) {
console.warn('Could not load data.json (likely due to CORS on local file system). Using fallback data.', error);
// Fallback Data if JSON fetch fails
products = [
{ id: 1, name: "Wireless Headphones", price: 299, category: "tech", image: "http://static.photos/technology/640x360/1", rating: 4.8 },
{ id: 2, name: "Mechanical Keyboard", price: 149, category: "tech", image: "http://static.photos/workspace/640x360/2", rating: 4.7 },
{ id: 3, name: "Modern Lamp", price: 89, category: "design", image: "http://static.photos/interior/640x360/3", rating: 4.5 },
{ id: 4, name: "Smart Watch", price: 399, category: "tech", image: "http://static.photos/technology/640x360/6", rating: 4.6 }
];
} finally {
// Hide Loader
loader.style.display = 'none';
renderProducts(products);
}
}
// --- Function: Render Products ---
function renderProducts(items) {
productGrid.innerHTML = '';
items.forEach(product => {
const card = document.createElement('shop-card');
// Set attributes for the web component
card.setAttribute('name', product.name);
card.setAttribute('price', product.price);
card.setAttribute('category', product.category);
card.setAttribute('image', product.image);
card.setAttribute('rating', product.rating);
productGrid.appendChild(card);
});
}
// --- Function: Filter Products ---
function filterProducts(category) {
// Update active button styles
const buttons = document.querySelectorAll('button[id^="filter-"]');
buttons.forEach(btn => {
if (btn.id === `filter-${category}`) {
btn.classList.remove('bg-white', 'text-gray-600');
btn.classList.add('bg-primary', 'text-white');
} else {
btn.classList.remove('bg-primary', 'text-white');
btn.classList.add('bg-white', 'text-gray-600');
}
});
if (category === 'all') {
renderProducts(products);
} else {
const filtered = products.filter(p => p.category === category);
renderProducts(filtered);
}
}
// --- Global Event Listener: Add to Cart ---
// We listen for a custom event dispatched from inside the Shadow DOM of the Web Component
window.addEventListener('add-to-cart', (e) => {
cartCount++;
updateCartDisplay();
showToast(`Added ${e.detail.productName} to cart!`);
});
// --- Global Event Listener: Remove Product ---
window.addEventListener('remove-product', (e) => {
const card = e.detail.element;
card.style.opacity = '0';
card.style.transform = 'scale(0.9)';
setTimeout(() => {
card.remove();
}, 300);
showToast('Product removed.');
});
function updateCartDisplay() {
// We dispatch an event to the navbar since we can't easily access its shadow DOM internals directly
window.dispatchEvent(new CustomEvent('update-cart-count', {
detail: { count: cartCount }
}));
}
// --- Function: Show Toast Notification ---
function showToast(message) {
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = 'toast-enter bg-dark text-white px-6 py-3 rounded-lg shadow-xl flex items-center gap-3';
toast.innerHTML = `
${message}
`;
container.appendChild(toast);
feather.replace(); // Refresh icons in new element
// Remove after 3 seconds
setTimeout(() => {
toast.classList.remove('toast-enter');
toast.classList.add('toast-exit');
setTimeout(() => {
toast.remove();
}, 300);
}, 3000);
}
// Initialize
loadProducts();
});