diff --git a/client/src/main.js b/client/src/main.js index d9e9fd0..27be617 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -39,6 +39,16 @@ const markup = ` + + @@ -59,6 +69,10 @@ const fileInfo = document.getElementById('fileInfo') const fileName = document.getElementById('fileName') const clearBtn = document.getElementById('clearBtn') const status = document.getElementById('status') +const submitBtn = document.getElementById('submitBtn') +const progressContainer = document.getElementById('progressContainer') +const progressBar = document.getElementById('progressBar') +const progressPercent = document.getElementById('progressPercent') function showStatus(text, ok = true) { status.textContent = text @@ -95,17 +109,61 @@ dropZone.addEventListener('drop', (e) => { fileInput.addEventListener('change', updateFileInfo) clearBtn.addEventListener('click', () => { fileInput.value = ''; updateFileInfo() }) -uploadForm.addEventListener('submit', async (e) => { +uploadForm.addEventListener('submit', (e) => { e.preventDefault() - if (!fileInput.files || !fileInput.files[0]) return showStatus('Selecciona un archivo .txt primero', false) - const fd = new FormData() - fd.append('cookies', fileInput.files[0]) - try { - const res = await fetch('/upload-cookies', { method: 'POST', body: fd }) - const json = await res.json() - if (res.ok) showStatus(json.message || 'Subida correcta') - else showStatus(json.message || json.error || 'Error al subir', false) - } catch (err) { - showStatus(err.message || 'Error de red', false) + + if (!fileInput.files || !fileInput.files[0]) { + return showStatus('Selecciona un archivo .txt primero', false) } + + const file = fileInput.files[0] + const fd = new FormData() + fd.append('cookies', file) + + // Reset UI + status.classList.add('hidden') + progressContainer.classList.remove('hidden') + progressBar.style.width = '0%' + progressPercent.textContent = '0%' + submitBtn.disabled = true + submitBtn.classList.add('opacity-50', 'cursor-not-allowed') + + const xhr = new XMLHttpRequest() + + xhr.upload.addEventListener('progress', (ev) => { + if (ev.lengthComputable) { + const percent = Math.round((ev.loaded / ev.total) * 100) + progressBar.style.width = percent + '%' + progressPercent.textContent = percent + '%' + } + }) + + xhr.onload = () => { + submitBtn.disabled = false + submitBtn.classList.remove('opacity-50', 'cursor-not-allowed') + + setTimeout(() => { + progressContainer.classList.add('hidden') + try { + const res = JSON.parse(xhr.responseText) + if (xhr.status >= 200 && xhr.status < 300) { + showStatus(res.message || 'Cookies actualizadas con éxito') + } else { + showStatus(res.message || 'Error en el servidor', false) + } + } catch (err) { + showStatus('Error al procesar respuesta', false) + } + }, 500) + } + + xhr.onerror = () => { + submitBtn.disabled = false + submitBtn.classList.remove('opacity-50', 'cursor-not-allowed') + progressContainer.classList.add('hidden') + showStatus('Error de conexión a la red', false) + } + + xhr.open('POST', '/upload-cookies') + xhr.send(fd) })