// 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' : ''}
${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);