Files
roi-theme/assets/js/footer-contact.js
FrankZamora bbc6ed2c98 Refactor: Reorganizar repositorio - Solo tema WordPress
Se movió el repositorio git desde la raíz de WordPress a la carpeta del tema.
Este commit limpia todos los archivos de WordPress del historial de tracking
y mantiene únicamente los archivos del tema apus-theme.

Cambios:
- Eliminado tracking de archivos de WordPress core
- Mantenido solo archivos del tema (97 archivos)
- Actualizado .gitignore para excluir carpetas de desarrollo
- Historial de commits anteriores se mantiene intacto

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 09:15:47 -06:00

344 lines
10 KiB
JavaScript

/**
* Footer Contact Form Handler (Issue #37)
*
* Maneja la validación, envío y tracking del formulario de contacto del footer.
* Incluye:
* - Validaciones de email y WhatsApp
* - Envío a webhook
* - Google Analytics 4 tracking
* - Estados de loading y mensajes de feedback
*
* @package Apus_Theme
* @since 1.0.0
*/
(function() {
'use strict';
// Configuración del webhook
const WEBHOOK_URL = 'https://hook.us2.make.com/iq8p4q9w50a12crlb58d4h1o6lwu4f47';
const FORM_SOURCE = 'APU Website - Footer Contact Form';
// Expresiones regulares para validación
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const WHATSAPP_REGEX = /^\+?[\d\s-]{10,15}$/;
/**
* Inicializar el formulario cuando el DOM está listo
*/
function init() {
const form = document.getElementById('footerContactForm');
if (!form) return;
// Agregar event listeners
form.addEventListener('submit', handleSubmit);
// Validación en tiempo real para campos específicos
const emailInput = document.getElementById('footerEmail');
const whatsappInput = document.getElementById('footerWhatsapp');
if (emailInput) {
emailInput.addEventListener('blur', function() {
validateEmail(this);
});
emailInput.addEventListener('input', function() {
if (this.classList.contains('is-invalid')) {
validateEmail(this);
}
});
}
if (whatsappInput) {
whatsappInput.addEventListener('blur', function() {
validateWhatsApp(this);
});
whatsappInput.addEventListener('input', function() {
if (this.classList.contains('is-invalid')) {
validateWhatsApp(this);
}
});
}
}
/**
* Validar email
* @param {HTMLInputElement} input - Campo de input
* @returns {boolean} - True si es válido
*/
function validateEmail(input) {
const value = input.value.trim();
const isValid = EMAIL_REGEX.test(value);
if (value === '') {
input.classList.remove('is-valid', 'is-invalid');
return true; // Si está vacío pero no es requerido, es válido
}
if (isValid) {
input.classList.remove('is-invalid');
input.classList.add('is-valid');
} else {
input.classList.remove('is-valid');
input.classList.add('is-invalid');
}
return isValid;
}
/**
* Validar WhatsApp (10-15 dígitos)
* @param {HTMLInputElement} input - Campo de input
* @returns {boolean} - True si es válido
*/
function validateWhatsApp(input) {
const value = input.value.trim();
// Remover espacios, guiones y signos + para contar solo dígitos
const digitsOnly = value.replace(/[\s\-+]/g, '');
const isValid = WHATSAPP_REGEX.test(value) && digitsOnly.length >= 10 && digitsOnly.length <= 15;
if (value === '') {
input.classList.remove('is-valid', 'is-invalid');
return false; // WhatsApp es requerido
}
if (isValid) {
input.classList.remove('is-invalid');
input.classList.add('is-valid');
} else {
input.classList.remove('is-valid');
input.classList.add('is-invalid');
}
return isValid;
}
/**
* Validar todos los campos del formulario
* @param {HTMLFormElement} form - Formulario
* @returns {boolean} - True si todo es válido
*/
function validateForm(form) {
let isValid = true;
// Validar campos requeridos
const fullName = form.querySelector('#footerFullName');
const email = form.querySelector('#footerEmail');
const whatsapp = form.querySelector('#footerWhatsapp');
if (fullName && fullName.value.trim() === '') {
fullName.classList.add('is-invalid');
isValid = false;
} else if (fullName) {
fullName.classList.remove('is-invalid');
fullName.classList.add('is-valid');
}
if (email && !validateEmail(email)) {
isValid = false;
}
if (whatsapp && !validateWhatsApp(whatsapp)) {
isValid = false;
}
return isValid;
}
/**
* Mostrar mensaje de feedback
* @param {string} message - Mensaje a mostrar
* @param {string} type - Tipo: 'success', 'danger', 'info'
*/
function showMessage(message, type) {
const messageDiv = document.getElementById('footerFormMessage');
if (!messageDiv) return;
messageDiv.className = 'col-12 mt-2 alert alert-' + type;
messageDiv.textContent = message;
messageDiv.style.display = 'block';
messageDiv.classList.add('show');
// Scroll suave al mensaje
messageDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
// Auto-ocultar mensajes de éxito después de 5 segundos
if (type === 'success') {
setTimeout(function() {
hideMessage();
}, 5000);
}
}
/**
* Ocultar mensaje
*/
function hideMessage() {
const messageDiv = document.getElementById('footerFormMessage');
if (!messageDiv) return;
messageDiv.classList.remove('show');
setTimeout(function() {
messageDiv.style.display = 'none';
}, 150);
}
/**
* Trackear evento en Google Analytics 4
* @param {string} eventName - Nombre del evento
* @param {Object} params - Parámetros adicionales
*/
function trackGA4Event(eventName, params) {
if (typeof gtag === 'function') {
gtag('event', eventName, params);
} else if (typeof dataLayer !== 'undefined') {
dataLayer.push({
'event': eventName,
...params
});
}
}
/**
* Preparar datos del formulario
* @param {HTMLFormElement} form - Formulario
* @returns {Object} - Datos del formulario
*/
function getFormData(form) {
return {
fullName: form.querySelector('#footerFullName').value.trim(),
company: form.querySelector('#footerCompany').value.trim() || 'N/A',
whatsapp: form.querySelector('#footerWhatsapp').value.trim(),
email: form.querySelector('#footerEmail').value.trim(),
comments: form.querySelector('#footerComments').value.trim() || 'Sin comentarios',
source: FORM_SOURCE,
timestamp: new Date().toISOString(),
pageUrl: window.location.href,
pageTitle: document.title
};
}
/**
* Enviar datos al webhook
* @param {Object} data - Datos a enviar
* @returns {Promise} - Promesa de fetch
*/
async function sendToWebhook(data) {
const response = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error('Error en el servidor: ' + response.status);
}
return response;
}
/**
* Resetear el formulario
* @param {HTMLFormElement} form - Formulario
*/
function resetForm(form) {
form.reset();
// Remover todas las clases de validación
const inputs = form.querySelectorAll('.form-control');
inputs.forEach(function(input) {
input.classList.remove('is-valid', 'is-invalid');
});
}
/**
* Manejar el envío del formulario
* @param {Event} e - Evento de submit
*/
async function handleSubmit(e) {
e.preventDefault();
const form = e.target;
const submitBtn = form.querySelector('button[type="submit"]');
// Ocultar mensaje anterior
hideMessage();
// Validar formulario
if (!validateForm(form)) {
showMessage('Por favor, completa todos los campos requeridos correctamente.', 'danger');
// Track error de validación
trackGA4Event('form_validation_error', {
form_name: 'footer_contact',
form_source: FORM_SOURCE
});
return;
}
// Deshabilitar botón y mostrar loading
submitBtn.disabled = true;
submitBtn.classList.add('loading');
const originalText = submitBtn.innerHTML;
// Track inicio de envío
trackGA4Event('form_submit_start', {
form_name: 'footer_contact',
form_source: FORM_SOURCE
});
try {
// Preparar y enviar datos
const formData = getFormData(form);
await sendToWebhook(formData);
// Éxito
showMessage('¡Gracias por tu mensaje! Nos pondremos en contacto contigo pronto.', 'success');
resetForm(form);
// Track éxito
trackGA4Event('form_submit_success', {
form_name: 'footer_contact',
form_source: FORM_SOURCE,
has_company: formData.company !== 'N/A',
has_comments: formData.comments !== 'Sin comentarios'
});
// Track conversión
trackGA4Event('generate_lead', {
currency: 'MXN',
value: 1,
form_name: 'footer_contact',
form_source: FORM_SOURCE
});
} catch (error) {
console.error('Error al enviar el formulario:', error);
showMessage('Hubo un error al enviar tu mensaje. Por favor, intenta nuevamente.', 'danger');
// Track error
trackGA4Event('form_submit_error', {
form_name: 'footer_contact',
form_source: FORM_SOURCE,
error_message: error.message
});
} finally {
// Restaurar botón
submitBtn.disabled = false;
submitBtn.classList.remove('loading');
submitBtn.innerHTML = originalText;
}
}
// Inicializar cuando el DOM esté listo
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();