// HokoriTemp - JavaScript para la página de vista // DOM Elements const linksContainer = document.getElementById('linksContainer'); const emptyState = document.getElementById('emptyState'); const loadingState = document.getElementById('loadingState'); const confirmModal = document.getElementById('confirmModal'); const confirmDeleteBtn = document.getElementById('confirmDeleteBtn'); const cancelDeleteBtn = document.getElementById('cancelDeleteBtn'); // Variable para almacenar el ID del archivo a eliminar let fileToDelete = null; // Load links on page load document.addEventListener('DOMContentLoaded', loadLinks); // Event listeners para el modal confirmDeleteBtn.addEventListener('click', confirmDelete); cancelDeleteBtn.addEventListener('click', hideModal); // Cerrar modal al hacer clic fuera de él confirmModal.addEventListener('click', (e) => { if (e.target === confirmModal) { hideModal(); } }); // Cerrar modal con Escape document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !confirmModal.classList.contains('hidden')) { hideModal(); } }); async function loadLinks() { try { const response = await fetch('/api/links'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const links = await response.json(); // Hide loading loadingState.classList.add('hidden'); if (links.length === 0) { showEmptyState(); } else { showLinks(links); } } catch (error) { console.error('Error cargando enlaces:', error); loadingState.classList.add('hidden'); showError('Error al cargar los enlaces'); } } function showEmptyState() { emptyState.classList.remove('hidden'); } function showLinks(links) { const linksHTML = links.map(link => createLinkCard(link)).join(''); linksContainer.innerHTML = linksHTML; } function createLinkCard(link) { const createdAt = new Date(link.created_at); const expiresAt = new Date(link.expires_at); const timeLeft = getTimeLeft(expiresAt); const isExpired = expiresAt <= new Date(); const fileSize = formatFileSize(link.file_size); return `

${link.filename}

Creado: ${formatDate(createdAt)} • ${fileSize} • ${link.download_count} descarga${link.download_count !== 1 ? 's' : ''}

Enlace:
${isExpired ? 'Expirado' : `Expira en: ${timeLeft}`} ${isExpired ? '' : ` `}
`; } function getTimeLeft(expiresAt) { const now = new Date(); const diff = expiresAt - now; if (diff <= 0) return 'Expirado'; const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); if (hours > 0) { return `${hours}h ${minutes}m`; } else { return `${minutes}m`; } } function formatDate(date) { return date.toLocaleString('es-ES', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } function copyLink(url) { navigator.clipboard.writeText(url).then(() => { // Show feedback const button = event.target; const originalText = button.textContent; button.textContent = '¡Copiado!'; setTimeout(() => { button.textContent = originalText; }, 2000); // Show notification showNotification('Enlace copiado al portapapeles', 'success'); }).catch(() => { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = url; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); const button = event.target; const originalText = button.textContent; button.textContent = '¡Copiado!'; setTimeout(() => { button.textContent = originalText; }, 2000); showNotification('Enlace copiado al portapapeles', 'success'); }); } function openLink(url) { window.open(url, '_blank'); } function showDeleteModal(linkId) { fileToDelete = linkId; confirmModal.classList.remove('hidden'); } function hideModal() { confirmModal.classList.add('hidden'); fileToDelete = null; } async function confirmDelete() { if (!fileToDelete) return; try { const response = await fetch(`/api/delete/${fileToDelete}`, { method: 'DELETE' }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); if (result.success) { showNotification('Archivo eliminado permanentemente', 'success'); hideModal(); // Recargar la página para actualizar la lista location.reload(); } else { throw new Error(result.error || 'Error al eliminar el archivo'); } } catch (error) { console.error('Error eliminando archivo:', error); showNotification('Error al eliminar el archivo', 'error'); hideModal(); } } // Función para mostrar notificaciones function showNotification(message, type = 'info') { // Crear elemento de notificación const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; // Agregar al DOM document.body.appendChild(notification); // Mostrar con animación setTimeout(() => { notification.classList.add('show'); }, 100); // Ocultar después de 3 segundos setTimeout(() => { notification.classList.remove('show'); setTimeout(() => { document.body.removeChild(notification); }, 300); }, 3000); } // Función para mostrar errores function showError(message) { showNotification(message, 'error'); } // Auto-refresh every minute to update expiration times setInterval(() => { const links = document.querySelectorAll('[data-expires-at]'); links.forEach(linkElement => { const expiresAt = new Date(linkElement.dataset.expiresAt); const timeLeftElement = linkElement.querySelector('.time-left'); if (timeLeftElement) { timeLeftElement.textContent = getTimeLeft(expiresAt); } }); }, 60000);