/** * Asset Preview Module * * Handles asset preview thumbnails, lightbox, and detail views */ export class AssetPreview { constructor() { this.lightbox = null; this.init(); } init() { this.setupThumbnailClicks(); this.setupLightbox(); this.setupCopyUrl(); this.setupVariantDeletion(); } setupThumbnailClicks() { document.addEventListener('click', (e) => { const thumbnail = e.target.closest('.asset-preview-thumbnail'); if (!thumbnail) return; const assetId = thumbnail.dataset.assetId; if (!assetId) return; // Navigate to detail view window.location.href = `/admin/assets/${assetId}`; }); } setupLightbox() { // Create lightbox HTML const lightboxHTML = ` `; // Add lightbox to body if not exists if (!document.getElementById('asset-lightbox')) { document.body.insertAdjacentHTML('beforeend', lightboxHTML); this.lightbox = document.getElementById('asset-lightbox'); } else { this.lightbox = document.getElementById('asset-lightbox'); } // Setup image clicks for lightbox document.addEventListener('click', (e) => { const img = e.target.closest('img[data-lightbox]'); if (!img) return; e.preventDefault(); this.openLightbox(img.src, img.alt, img.dataset.filename, img.dataset.size); }); // Close lightbox document.addEventListener('click', (e) => { if (e.target.closest('[data-close-lightbox]') || e.target === this.lightbox) { this.closeLightbox(); } }); // Close on Escape key document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && this.lightbox && this.lightbox.style.display !== 'none') { this.closeLightbox(); } }); } openLightbox(imageUrl, alt, filename, size) { if (!this.lightbox) return; const img = this.lightbox.querySelector('.asset-lightbox__image'); const filenameEl = this.lightbox.querySelector('.asset-lightbox__filename'); const sizeEl = this.lightbox.querySelector('.asset-lightbox__size'); img.src = imageUrl; img.alt = alt; if (filenameEl) filenameEl.textContent = filename || alt; if (sizeEl) sizeEl.textContent = size || ''; this.lightbox.style.display = 'flex'; document.body.style.overflow = 'hidden'; } closeLightbox() { if (!this.lightbox) return; this.lightbox.style.display = 'none'; document.body.style.overflow = ''; } setupCopyUrl() { document.addEventListener('click', async (e) => { const copyButton = e.target.closest('[data-copy-url]'); if (!copyButton) return; e.preventDefault(); try { const url = copyButton.href; const response = await fetch(url); const data = await response.json(); const assetUrl = data.url || url; await navigator.clipboard.writeText(assetUrl); // Show success feedback const originalText = copyButton.textContent; copyButton.textContent = 'Copied!'; copyButton.classList.add('copied'); setTimeout(() => { copyButton.textContent = originalText; copyButton.classList.remove('copied'); }, 2000); } catch (error) { console.error('Failed to copy URL:', error); alert('Failed to copy URL'); } }); } setupVariantDeletion() { document.addEventListener('click', async (e) => { const deleteButton = e.target.closest('[data-delete-variant]'); if (!deleteButton) return; e.preventDefault(); const variant = deleteButton.dataset.variant; const assetId = deleteButton.closest('[data-asset-id]')?.dataset.assetId || window.location.pathname.split('/').pop(); if (!confirm(`Are you sure you want to delete variant "${variant}"?`)) { return; } try { deleteButton.disabled = true; deleteButton.textContent = 'Deleting...'; const response = await fetch(`/api/v1/assets/${assetId}/variants/${variant}`, { method: 'DELETE', headers: { 'X-Requested-With': 'XMLHttpRequest', }, }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } // Remove variant item from DOM deleteButton.closest('.variant-item')?.remove(); // Show success message if (window.Toast) { window.Toast.success(`Variant "${variant}" deleted successfully`); } } catch (error) { console.error('Failed to delete variant:', error); deleteButton.disabled = false; deleteButton.textContent = 'Delete'; if (window.Toast) { window.Toast.error(`Failed to delete variant: ${error.message}`); } else { alert(`Failed to delete variant: ${error.message}`); } } }); } } // Auto-initialize document.addEventListener('DOMContentLoaded', () => { new AssetPreview(); });