<div class="upload-container">
<div class="upload-demo">
<div class="file-upload-area" id="uploadArea">
<div class="upload-content">
<div class="upload-icon">📁</div>
<h3>Arrastra y Suelta Archivos</h3>
<p>o <span class="browse-link" id="browseLink">explora archivos</span></p>
<p class="upload-hint">Compatible con JPG, PNG, PDF hasta 10MB</p>
</div>
<input type="file" id="fileInput" class="file-input" multiple accept=".jpg,.jpeg,.png,.pdf">
</div>
<div class="upload-progress" id="uploadProgress" style="display: none;">
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="progress-text" id="progressText">Cargando... 0%</div>
</div>
<div class="uploaded-files" id="uploadedFiles"></div>
</div>
</div>
.upload-container {
background: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%);
padding: 30px;
border-radius: 20px;
max-width: 600px;
margin: 0 auto;
}
.file-upload-area {
border: 3px dashed #cbd5e1;
border-radius: 15px;
padding: 40px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
background: white;
position: relative;
}
.file-upload-area:hover,
.file-upload-area.dragover {
border-color: #667eea;
background: rgba(102, 126, 234, 0.05);
transform: translateY(-2px);
}
.file-upload-area.dragover {
background: rgba(102, 126, 234, 0.1);
}
.upload-icon {
font-size: 3rem;
margin-bottom: 20px;
}
.file-upload-area h3 {
margin: 0 0 15px 0;
color: #333;
font-size: 1.5rem;
font-weight: 600;
}
.file-upload-area p {
margin: 0 0 10px 0;
color: #666;
}
.browse-link {
color: #667eea;
font-weight: 600;
cursor: pointer;
text-decoration: underline;
}
.browse-link:hover {
color: #5a6fd8;
}
.upload-hint {
font-size: 0.9rem;
color: #999 !important;
}
.file-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
.upload-progress {
margin: 25px 0;
}
.progress-bar {
height: 10px;
background: #e2e8f0;
border-radius: 5px;
overflow: hidden;
margin-bottom: 15px;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
border-radius: 5px;
width: 0%;
transition: width 0.3s ease;
}
.progress-text {
text-align: center;
font-weight: 500;
color: #666;
}
.uploaded-files {
margin-top: 25px;
}
.file-item {
display: flex;
align-items: center;
gap: 15px;
padding: 15px;
background: white;
border-radius: 12px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
margin-bottom: 15px;
animation: slideInUp 0.3s ease;
}
.file-icon {
font-size: 2rem;
}
.file-info {
flex: 1;
}
.file-name {
font-weight: 600;
color: #333;
margin-bottom: 5px;
word-break: break-all;
}
.file-size {
font-size: 0.9rem;
color: #666;
}
.file-actions {
display: flex;
gap: 10px;
}
.file-action-btn {
background: none;
border: none;
font-size: 1.2rem;
cursor: pointer;
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.file-action-btn.delete {
color: #ef4444;
}
.file-action-btn.delete:hover {
background: #fee2e2;
}
.file-action-btn.download {
color: #667eea;
}
.file-action-btn.download:hover {
background: #dbeafe;
}
.file-preview {
width: 50px;
height: 50px;
border-radius: 8px;
object-fit: cover;
background: #f1f5f9;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
}
.file-preview img {
width: 100%;
height: 100%;
border-radius: 8px;
object-fit: cover;
}
/* Animaciones */
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(102, 126, 234, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0);
}
}
.file-upload-area.dragover {
animation: pulse 2s infinite;
}
/* Responsivo */
@media (max-width: 768px) {
.upload-container {
padding: 20px;
}
.file-upload-area {
padding: 30px 15px;
}
.upload-icon {
font-size: 2.5rem;
}
.file-upload-area h3 {
font-size: 1.3rem;
}
}
document.addEventListener('DOMContentLoaded', function() {
// Obtener elementos del DOM
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const browseLink = document.getElementById('browseLink');
const uploadProgress = document.getElementById('uploadProgress');
const progressFill = document.getElementById('progressFill');
const progressText = document.getElementById('progressText');
const uploadedFiles = document.getElementById('uploadedFiles');
// Agregar escuchadores de eventos
browseLink.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
// Eventos de arrastrar y soltar
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
uploadArea.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, unhighlight, false);
});
function highlight() {
uploadArea.classList.add('dragover');
}
function unhighlight() {
uploadArea.classList.remove('dragover');
}
// Manejar archivos soltados
uploadArea.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
handleFiles(files);
}
// Manejar selección de archivos
function handleFileSelect(e) {
const files = e.target.files;
handleFiles(files);
}
// Procesar archivos
function handleFiles(files) {
[...files].forEach(uploadFile);
}
// Cargar archivo (simulado)
function uploadFile(file) {
// Mostrar progreso
uploadProgress.style.display = 'block';
// Crear elemento de archivo
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-preview">
${getFileIcon(file)}
</div>
<div class="file-info">
<div class="file-name">${file.name}</div>
<div class="file-size">${formatFileSize(file.size)}</div>
</div>
<div class="file-actions">
<button class="file-action-btn delete" title="Eliminar">×</button>
</div>
`;
uploadedFiles.appendChild(fileItem);
// Simular progreso de carga
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 10;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
// Actualizar UI cuando se completa la carga
progressText.textContent = '¡Carga completada!';
progressFill.style.width = '100%';
// Agregar botón de descarga
const downloadBtn = document.createElement('button');
downloadBtn.className = 'file-action-btn download';
downloadBtn.title = 'Descargar';
downloadBtn.innerHTML = '↓';
fileItem.querySelector('.file-actions').appendChild(downloadBtn);
// Agregar funcionalidad de eliminación
const deleteBtn = fileItem.querySelector('.delete');
deleteBtn.addEventListener('click', () => {
fileItem.style.animation = 'fadeOut 0.3s ease';
setTimeout(() => {
fileItem.remove();
}, 300);
});
// Agregar funcionalidad de descarga
downloadBtn.addEventListener('click', () => {
alert(`Descargando ${file.name}`);
});
// Ocultar progreso después de un retraso
setTimeout(() => {
uploadProgress.style.display = 'none';
progressFill.style.width = '0%';
progressText.textContent = 'Cargando... 0%';
}, 2000);
}
progressFill.style.width = `${progress}%`;
progressText.textContent = `Cargando... ${Math.round(progress)}%`;
}, 100);
}
// Obtener ícono de archivo basado en el tipo de archivo
function getFileIcon(file) {
const fileType = file.type.split('/')[0];
const fileExtension = file.name.split('.').pop().toLowerCase();
if (fileType === 'image') {
// Para archivos de imagen, crearíamos una vista previa en una aplicación real
return '🖼️';
} else if (fileExtension === 'pdf') {
return '📄';
} else {
return '📁';
}
}
// Formatear tamaño de archivo
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];
}
});