<div class="contact-container">
<div class="contact-header">
<h1 class="contact-title">Ponte en Contacto</h1>
<p class="contact-subtitle">Nos encantaría saber de ti. Envíanos un mensaje y te responderemos lo antes posible.</p>
</div>
<div class="contact-content">
<!-- Información de Contacto -->
<div class="contact-info">
<div class="info-item">
<div class="info-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
</svg>
</div>
<div class="info-content">
<h3>Dirección</h3>
<p>Calle Empresarial 123<br>Suite 100<br>Madrid, España 28001</p>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/>
</svg>
</div>
<div class="info-content">
<h3>Teléfono</h3>
<p>+34 (91) 123-4567<br>Lun-Vie 9:00-18:00 CET</p>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>
</svg>
</div>
<div class="info-content">
<h3>Email</h3>
<p>hola@empresa.com<br>soporte@empresa.com</p>
</div>
</div>
<div class="social-links">
<h3>Síguenos</h3>
<div class="social-icons">
<a href="#" class="social-link">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
</svg>
</a>
<a href="#" class="social-link">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M22.46 6c-.77.35-1.6.58-2.46.69.88-.53 1.56-1.37 1.88-2.38-.83.5-1.75.85-2.72 1.05C18.37 4.5 17.26 4 16 4c-2.35 0-4.27 1.92-4.27 4.29 0 .34.04.67.11.98C8.28 9.09 5.11 7.38 3 4.79c-.37.63-.58 1.37-.58 2.15 0 1.49.75 2.81 1.91 3.56-.71 0-1.37-.2-1.95-.5v.03c0 2.08 1.48 3.82 3.44 4.21a4.22 4.22 0 0 1-1.93.07 4.28 4.28 0 0 0 4 2.98 8.521 8.521 0 0 1-5.33 1.84c-.34 0-.68-.02-1.02-.06C3.44 20.29 5.7 21 8.12 21 16 21 20.33 14.46 20.33 8.79c0-.19 0-.37-.01-.56.84-.6 1.56-1.36 2.14-2.23z"/>
</svg>
</a>
<a href="#" class="social-link">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg>
</a>
</div>
</div>
</div>
<!-- Formulario de Contacto -->
<div class="contact-form-wrapper">
<form class="contact-form" id="contactForm">
<div class="form-row">
<div class="form-group">
<label for="firstName" class="form-label">Nombre *</label>
<input type="text" id="firstName" name="firstName" class="form-input" required>
<span class="form-error" id="firstNameError"></span>
</div>
<div class="form-group">
<label for="lastName" class="form-label">Apellidos *</label>
<input type="text" id="lastName" name="lastName" class="form-input" required>
<span class="form-error" id="lastNameError"></span>
</div>
</div>
<div class="form-group">
<label for="email" class="form-label">Correo Electrónico *</label>
<input type="email" id="email" name="email" class="form-input" required>
<span class="form-error" id="emailError"></span>
</div>
<div class="form-group">
<label for="phone" class="form-label">Número de Teléfono</label>
<input type="tel" id="phone" name="phone" class="form-input">
<span class="form-error" id="phoneError"></span>
</div>
<div class="form-group">
<label for="subject" class="form-label">Asunto *</label>
<select id="subject" name="subject" class="form-select" required>
<option value="">Selecciona un asunto</option>
<option value="general">Consulta General</option>
<option value="support">Soporte Técnico</option>
<option value="sales">Pregunta de Ventas</option>
<option value="partnership">Colaboración</option>
<option value="other">Otro</option>
</select>
<span class="form-error" id="subjectError"></span>
</div>
<div class="form-group">
<label for="message" class="form-label">Mensaje *</label>
<textarea id="message" name="message" class="form-textarea" rows="5" placeholder="Cuéntanos más sobre tu consulta..." required></textarea>
<span class="form-error" id="messageError"></span>
<div class="character-count">
<span id="charCount">0</span>/500 caracteres
</div>
</div>
<div class="form-group">
<label class="file-upload-label">
<input type="file" id="attachment" name="attachment" class="file-input" multiple accept=".pdf,.doc,.docx,.txt,.jpg,.png">
<div class="file-upload-area" id="fileUploadArea">
<svg class="upload-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" />
</svg>
<span class="upload-text">Arrastra archivos aquí o haz clic para subir</span>
<span class="upload-hint">PDF, DOC, TXT, JPG, PNG (Máx 5MB cada uno)</span>
</div>
</label>
<div class="uploaded-files" id="uploadedFiles"></div>
</div>
<div class="form-group checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="newsletter" name="newsletter" class="checkbox-input">
<span class="checkbox-custom"></span>
<span class="checkbox-text">Suscribirse a nuestro boletín para actualizaciones y noticias</span>
</label>
</div>
<div class="form-group checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="privacy" name="privacy" class="checkbox-input" required>
<span class="checkbox-custom"></span>
<span class="checkbox-text">Acepto la <a href="#" class="privacy-link">Política de Privacidad</a> y los <a href="#" class="privacy-link">Términos de Servicio</a> *</span>
</label>
<span class="form-error" id="privacyError"></span>
</div>
<button type="submit" class="submit-btn" id="submitBtn">
<span class="btn-text">Enviar Mensaje</span>
<span class="btn-loading" style="display: none;">
<svg class="loading-spinner" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-dasharray="32" stroke-dashoffset="32">
<animate attributeName="stroke-dasharray" dur="2s" values="0 32;16 16;0 32;0 32" repeatCount="indefinite"/>
<animate attributeName="stroke-dashoffset" dur="2s" values="0;-16;-32;-32" repeatCount="indefinite"/>
</circle>
</svg>
Enviando...
</span>
</button>
</form>
<!-- Mensajes de Éxito/Error -->
<div class="form-message success-message" id="successMessage" style="display: none;">
<svg class="message-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
<div class="message-content">
<h3>¡Mensaje Enviado Exitosamente!</h3>
<p>Gracias por contactarnos. Te responderemos dentro de 24 horas.</p>
</div>
</div>
<div class="form-message error-message" id="errorMessage" style="display: none;">
<svg class="message-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
</svg>
<div class="message-content">
<h3>Error al Enviar Mensaje</h3>
<p>Hubo un error al enviar tu mensaje. Por favor intenta de nuevo o contáctanos directamente.</p>
</div>
</div>
</div>
</div>
</div>
.contact-container {
max-width: 1200px;
margin: 0 auto;
padding: 48px 24px;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
.contact-header {
text-align: center;
margin-bottom: 48px;
}
.contact-title {
font-size: 48px;
font-weight: 700;
color: #1a202c;
margin: 0 0 16px 0;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.contact-subtitle {
font-size: 18px;
color: #6b7280;
margin: 0;
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.contact-content {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 48px;
align-items: start;
}
/* Contact Info */
.contact-info {
background: white;
border-radius: 16px;
padding: 32px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
height: fit-content;
}
.info-item {
display: flex;
gap: 16px;
margin-bottom: 32px;
}
.info-item:last-of-type {
margin-bottom: 24px;
}
.info-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
flex-shrink: 0;
}
.info-icon svg {
width: 24px;
height: 24px;
}
.info-content h3 {
font-size: 18px;
font-weight: 600;
color: #1a202c;
margin: 0 0 8px 0;
}
.info-content p {
font-size: 14px;
color: #6b7280;
margin: 0;
line-height: 1.5;
}
.social-links {
border-top: 1px solid #e5e7eb;
padding-top: 24px;
}
.social-links h3 {
font-size: 16px;
font-weight: 600;
color: #1a202c;
margin: 0 0 16px 0;
}
.social-icons {
display: flex;
gap: 12px;
}
.social-link {
width: 40px;
height: 40px;
background: #f3f4f6;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: #6b7280;
text-decoration: none;
transition: all 0.3s ease;
}
.social-link:hover {
background: #667eea;
color: white;
transform: translateY(-2px);
}
.social-link svg {
width: 20px;
height: 20px;
}
/* Contact Form */
.contact-form-wrapper {
background: white;
border-radius: 16px;
padding: 32px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
position: relative;
}
.contact-form {
display: flex;
flex-direction: column;
gap: 24px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.form-label {
font-size: 14px;
font-weight: 500;
color: #374151;
}
.form-input,
.form-select,
.form-textarea {
padding: 12px 16px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 16px;
transition: all 0.3s ease;
background: white;
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-input.error,
.form-select.error,
.form-textarea.error {
border-color: #ef4444;
}
.form-input.success,
.form-select.success,
.form-textarea.success {
border-color: #10b981;
}
.form-textarea {
resize: vertical;
min-height: 120px;
}
.form-error {
font-size: 12px;
color: #ef4444;
margin-top: 4px;
opacity: 0;
transform: translateY(-4px);
transition: all 0.3s ease;
}
.form-error.show {
opacity: 1;
transform: translateY(0);
}
.character-count {
font-size: 12px;
color: #9ca3af;
text-align: right;
margin-top: 4px;
}
/* File Upload */
.file-upload-label {
cursor: pointer;
}
.file-input {
display: none;
}
.file-upload-area {
border: 2px dashed #d1d5db;
border-radius: 8px;
padding: 32px 16px;
text-align: center;
transition: all 0.3s ease;
background: #f9fafb;
}
.file-upload-area:hover {
border-color: #667eea;
background: #f0f4ff;
}
.file-upload-area.dragover {
border-color: #667eea;
background: #e0e7ff;
transform: scale(1.02);
}
.upload-icon {
width: 48px;
height: 48px;
color: #9ca3af;
margin-bottom: 16px;
}
.upload-text {
display: block;
font-size: 16px;
font-weight: 500;
color: #374151;
margin-bottom: 4px;
}
.upload-hint {
font-size: 12px;
color: #9ca3af;
}
.uploaded-files {
margin-top: 16px;
}
.uploaded-file {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
background: #f3f4f6;
border-radius: 6px;
margin-bottom: 8px;
}
.file-info {
display: flex;
align-items: center;
gap: 8px;
}
.file-icon {
width: 16px;
height: 16px;
color: #6b7280;
}
.file-name {
font-size: 14px;
color: #374151;
}
.file-size {
font-size: 12px;
color: #9ca3af;
}
.remove-file {
background: none;
border: none;
color: #ef4444;
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: background 0.3s ease;
}
.remove-file:hover {
background: #fee2e2;
}
.remove-file svg {
width: 16px;
height: 16px;
}
/* Checkbox */
.checkbox-group {
margin-top: 8px;
}
.checkbox-label {
display: flex;
align-items: flex-start;
gap: 12px;
cursor: pointer;
}
.checkbox-input {
display: none;
}
.checkbox-custom {
width: 20px;
height: 20px;
border: 2px solid #d1d5db;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
flex-shrink: 0;
margin-top: 2px;
}
.checkbox-input:checked + .checkbox-custom {
background: #667eea;
border-color: #667eea;
}
.checkbox-input:checked + .checkbox-custom::after {
content: '✓';
color: white;
font-size: 12px;
font-weight: bold;
}
.checkbox-text {
font-size: 14px;
color: #374151;
line-height: 1.5;
}
.privacy-link {
color: #667eea;
text-decoration: none;
}
.privacy-link:hover {
text-decoration: underline;
}
/* Submit Button */
.submit-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 16px 32px;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 16px rgba(102, 126, 234, 0.3);
}
.submit-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
transform: none;
}
.btn-text,
.btn-loading {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.loading-spinner {
width: 20px;
height: 20px;
}
/* Messages */
.form-message {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
border-radius: 8px;
margin-top: 24px;
animation: slideIn 0.3s ease;
}
.success-message {
background: #ecfdf5;
border: 1px solid #a7f3d0;
color: #065f46;
}
.error-message {
background: #fef2f2;
border: 1px solid #fca5a5;
color: #991b1b;
}
.message-icon {
width: 24px;
height: 24px;
flex-shrink: 0;
}
.message-content h3 {
font-size: 16px;
font-weight: 600;
margin: 0 0 4px 0;
}
.message-content p {
font-size: 14px;
margin: 0;
opacity: 0.8;
}
/* Animations */
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-4px); }
75% { transform: translateX(4px); }
}
.form-group.error {
animation: shake 0.5s ease;
}
/* Responsive Design */
@media (max-width: 768px) {
.contact-container {
padding: 24px 16px;
}
.contact-title {
font-size: 32px;
}
.contact-subtitle {
font-size: 16px;
}
.contact-content {
grid-template-columns: 1fr;
gap: 32px;
}
.contact-info {
order: 2;
}
.contact-form-wrapper {
order: 1;
}
.form-row {
grid-template-columns: 1fr;
gap: 24px;
}
.info-item {
flex-direction: column;
text-align: center;
gap: 12px;
}
.info-icon {
align-self: center;
}
.social-icons {
justify-content: center;
}
}
@media (max-width: 480px) {
.contact-info,
.contact-form-wrapper {
padding: 24px 16px;
}
.file-upload-area {
padding: 24px 12px;
}
.upload-icon {
width: 32px;
height: 32px;
}
.submit-btn {
padding: 14px 24px;
}
}
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('contactForm');
const submitBtn = document.getElementById('submitBtn');
const btnText = submitBtn.querySelector('.btn-text');
const btnLoading = submitBtn.querySelector('.btn-loading');
const successMessage = document.getElementById('successMessage');
const errorMessage = document.getElementById('errorMessage');
const fileInput = document.getElementById('attachment');
const fileUploadArea = document.getElementById('fileUploadArea');
const uploadedFiles = document.getElementById('uploadedFiles');
const messageTextarea = document.getElementById('message');
const charCount = document.getElementById('charCount');
let uploadedFilesList = [];
// Reglas de validación del formulario
const validationRules = {
firstName: {
required: true,
minLength: 2,
pattern: /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+$/,
message: 'El nombre debe tener al menos 2 caracteres y contener solo letras'
},
lastName: {
required: true,
minLength: 2,
pattern: /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+$/,
message: 'Los apellidos deben tener al menos 2 caracteres y contener solo letras'
},
email: {
required: true,
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: 'Por favor ingresa una dirección de correo válida'
},
phone: {
pattern: /^[\+]?[1-9][\d]{0,15}$/,
message: 'Por favor ingresa un número de teléfono válido'
},
subject: {
required: true,
message: 'Por favor selecciona un asunto'
},
message: {
required: true,
minLength: 10,
maxLength: 500,
message: 'El mensaje debe tener entre 10 y 500 caracteres'
},
privacy: {
required: true,
message: 'Debes aceptar la política de privacidad'
}
};
// Validación en tiempo real
Object.keys(validationRules).forEach(fieldName => {
const field = document.getElementById(fieldName);
if (field) {
field.addEventListener('blur', () => validateField(fieldName));
field.addEventListener('input', () => {
clearFieldError(fieldName);
if (fieldName === 'message') {
updateCharacterCount();
}
});
}
});
// Contador de caracteres para el mensaje
function updateCharacterCount() {
const count = messageTextarea.value.length;
charCount.textContent = count;
if (count > 500) {
charCount.style.color = '#ef4444';
} else if (count > 400) {
charCount.style.color = '#f59e0b';
} else {
charCount.style.color = '#9ca3af';
}
}
// Validación de campos
function validateField(fieldName) {
const field = document.getElementById(fieldName);
const rule = validationRules[fieldName];
const value = field.type === 'checkbox' ? field.checked : field.value.trim();
// Validación requerida
if (rule.required && (!value || value === '')) {
showFieldError(fieldName, rule.message || `${fieldName} es requerido`);
return false;
}
// Omitir otras validaciones si el campo está vacío y no es requerido
if (!value && !rule.required) {
clearFieldError(fieldName);
return true;
}
// Validación de longitud
if (rule.minLength && value.length < rule.minLength) {
showFieldError(fieldName, rule.message);
return false;
}
if (rule.maxLength && value.length > rule.maxLength) {
showFieldError(fieldName, rule.message);
return false;
}
// Validación de patrón
if (rule.pattern && !rule.pattern.test(value)) {
showFieldError(fieldName, rule.message);
return false;
}
// El campo es válido
clearFieldError(fieldName);
field.classList.add('success');
return true;
}
function showFieldError(fieldName, message) {
const field = document.getElementById(fieldName);
const errorElement = document.getElementById(fieldName + 'Error');
const formGroup = field.closest('.form-group');
field.classList.add('error');
field.classList.remove('success');
errorElement.textContent = message;
errorElement.classList.add('show');
formGroup.classList.add('error');
// Remover animación de sacudida después de que se complete
setTimeout(() => {
formGroup.classList.remove('error');
}, 500);
}
function clearFieldError(fieldName) {
const field = document.getElementById(fieldName);
const errorElement = document.getElementById(fieldName + 'Error');
field.classList.remove('error');
errorElement.classList.remove('show');
errorElement.textContent = '';
}
// Manejo de carga de archivos
fileInput.addEventListener('change', handleFileSelect);
// Arrastrar y soltar
fileUploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
fileUploadArea.classList.add('dragover');
});
fileUploadArea.addEventListener('dragleave', () => {
fileUploadArea.classList.remove('dragover');
});
fileUploadArea.addEventListener('drop', (e) => {
e.preventDefault();
fileUploadArea.classList.remove('dragover');
const files = Array.from(e.dataTransfer.files);
handleFiles(files);
});
function handleFileSelect(e) {
const files = Array.from(e.target.files);
handleFiles(files);
}
function handleFiles(files) {
const maxSize = 5 * 1024 * 1024; // 5MB
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'text/plain', 'image/jpeg', 'image/png'];
files.forEach(file => {
if (file.size > maxSize) {
alert(`El archivo "${file.name}" es demasiado grande. El tamaño máximo es 5MB.`);
return;
}
if (!allowedTypes.includes(file.type)) {
alert(`El archivo "${file.name}" no es un formato compatible.`);
return;
}
uploadedFilesList.push(file);
displayUploadedFile(file);
});
}
function displayUploadedFile(file) {
const fileElement = document.createElement('div');
fileElement.className = 'uploaded-file';
fileElement.innerHTML = `
<div class="file-info">
<svg class="file-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" />
</svg>
<span class="file-name">${file.name}</span>
<span class="file-size">(${formatFileSize(file.size)})</span>
</div>
<button type="button" class="remove-file" onclick="removeFile('${file.name}')">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
</button>
`;
uploadedFiles.appendChild(fileElement);
}
window.removeFile = function(fileName) {
uploadedFilesList = uploadedFilesList.filter(file => file.name !== fileName);
const fileElements = uploadedFiles.querySelectorAll('.uploaded-file');
fileElements.forEach(element => {
if (element.querySelector('.file-name').textContent === fileName) {
element.remove();
}
});
};
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];
}
// Envío del formulario
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Validar todos los campos
let isValid = true;
Object.keys(validationRules).forEach(fieldName => {
if (!validateField(fieldName)) {
isValid = false;
}
});
if (!isValid) {
return;
}
// Mostrar estado de carga
submitBtn.disabled = true;
btnText.style.display = 'none';
btnLoading.style.display = 'flex';
// Ocultar mensajes anteriores
successMessage.style.display = 'none';
errorMessage.style.display = 'none';
try {
// Simular llamada a API
await new Promise(resolve => setTimeout(resolve, 2000));
// Simular éxito/fallo aleatorio para demo
const success = Math.random() > 0.3;
if (success) {
showSuccessMessage();
form.reset();
uploadedFilesList = [];
uploadedFiles.innerHTML = '';
charCount.textContent = '0';
// Limpiar todos los estados de campos
Object.keys(validationRules).forEach(fieldName => {
clearFieldError(fieldName);
const field = document.getElementById(fieldName);
if (field) {
field.classList.remove('success', 'error');
}
});
} else {
showErrorMessage();
}
} catch (error) {
showErrorMessage();
} finally {
// Restablecer estado del botón
submitBtn.disabled = false;
btnText.style.display = 'flex';
btnLoading.style.display = 'none';
}
});
function showSuccessMessage() {
successMessage.style.display = 'flex';
successMessage.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
// Auto-ocultar después de 5 segundos
setTimeout(() => {
successMessage.style.display = 'none';
}, 5000);
}
function showErrorMessage() {
errorMessage.style.display = 'flex';
errorMessage.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
// Auto-ocultar después de 5 segundos
setTimeout(() => {
errorMessage.style.display = 'none';
}, 5000);
}
// Inicializar contador de caracteres
updateCharacterCount();
// Agregar gestión de foco para accesibilidad
const formElements = form.querySelectorAll('input, select, textarea, button');
formElements.forEach((element, index) => {
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
// Manejo personalizado de tab si es necesario
}
});
});
});