This commit is contained in:
2026-08-31 15:27:17 -03:00
commit 3663318076
23 changed files with 4140 additions and 0 deletions
+727
View File
@@ -0,0 +1,727 @@
/**
* IDE CONSULTORES - SCRIPT INSTITUCIONAL (JS ÚNICO)
* Maneja includes modulares, tema claro/oscuro, Brújula IDE, modales, catálogo de cursos, filtros y formularios.
*/
document.addEventListener('DOMContentLoaded', () => {
initApp();
});
async function initApp() {
initTheme();
await loadIncludes();
initModals();
initBrujulaIDE();
initAcademyCourses();
initSolucionesFilters();
initInsightsFeed();
initContactForm();
initCareersForm();
}
/* ==========================================================================
1. Carga Modular de Header y Footer (JS Nativo)
========================================================================== */
async function loadIncludes() {
const headerElem = document.getElementById('site-header');
const footerElem = document.getElementById('site-footer');
try {
if (headerElem) {
const headerRes = await fetch('/includes/header.html', { cache: 'no-store' });
if (headerRes.ok) {
headerElem.innerHTML = await headerRes.text();
highlightActiveNavLink();
attachHeaderEvents();
}
}
if (footerElem) {
const footerRes = await fetch('/includes/footer.html', { cache: 'no-store' });
if (footerRes.ok) {
footerElem.innerHTML = await footerRes.text();
}
}
} catch (err) {
console.warn('Nota: Inclusión modular de header/footer cargada con respaldo local.');
}
}
function highlightActiveNavLink() {
const currentPath = window.location.pathname;
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(link => {
const href = link.getAttribute('href');
if (!href) return;
// Comparación de página activa
if (
(currentPath === '/' || currentPath.endsWith('index.html')) && (href === '/' || href === 'index.html' || href === './') ||
(currentPath.includes(href) && href !== '/' && href !== 'index.html')
) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
}
function attachHeaderEvents() {
// Switch de Tema: usar clonación para evitar listeners duplicados
const themeToggle = document.getElementById('theme-toggle-btn');
if (themeToggle) {
const newThemeToggle = themeToggle.cloneNode(true);
themeToggle.parentNode.replaceChild(newThemeToggle, themeToggle);
newThemeToggle.addEventListener('click', toggleTheme);
}
// Botón de menú móvil y cierre del drawer: event delegation global.
// Evita depender de un nodo único (el header se inyecta de forma modular),
// de modo que funcione aunque el botón sea reemplazado por cloneNode.
const mobileDrawer = document.getElementById('mobile-menu-drawer');
document.addEventListener('click', (e) => {
const toggleClicked = e.target.closest('#mobile-menu-btn');
const insideDrawer = mobileDrawer && mobileDrawer.contains(e.target);
if (toggleClicked) {
if (mobileDrawer) {
const isOpen = mobileDrawer.classList.toggle('is-open');
toggleClicked.setAttribute('aria-expanded', isOpen);
}
} else if (mobileDrawer && mobileDrawer.classList.contains('is-open') && !insideDrawer) {
mobileDrawer.classList.remove('is-open');
const toggle = document.querySelector('#mobile-menu-btn');
if (toggle) toggle.setAttribute('aria-expanded', 'false');
}
});
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
toggleLogoTheme(currentTheme);
updateThemeIcon(currentTheme);
}
/* ==========================================================================
2. Selector de Modo Claro / Modo Oscuro con Persistencia
========================================================================== */
function initTheme() {
const savedTheme = localStorage.getItem('ide_theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);
updateThemeIcon(savedTheme);
toggleLogoTheme(savedTheme);
}
function toggleTheme() {
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('ide_theme', newTheme);
updateThemeIcon(newTheme);
toggleLogoTheme(newTheme);
const themeBtns = document.querySelectorAll('#theme-toggle-btn');
themeBtns.forEach(btn => {
btn.setAttribute('aria-label', newTheme === 'dark' ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro');
});
}
function updateThemeIcon(theme) {
const themeBtns = document.querySelectorAll('#theme-toggle-btn');
themeBtns.forEach(btn => {
btn.setAttribute('aria-label', theme === 'dark' ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro');
});
}
function toggleLogoTheme(theme) {
const logoLight = document.querySelector('.logo-light-only');
const logoDark = document.querySelector('.logo-dark-only');
if (logoLight && logoDark) {
if (theme === 'dark') {
logoLight.style.display = 'none';
logoDark.style.display = 'block';
} else {
logoLight.style.display = 'block';
logoDark.style.display = 'none';
}
}
}
/* ==========================================================================
4. Sistema de Modales (Pop-ups con Cierre por Clic Externo y ESC)
========================================================================== */
function initModals() {
const modalBackdrops = document.querySelectorAll('.modal-backdrop');
modalBackdrops.forEach(backdrop => {
// Cerrar al hacer clic en el backdrop (fuera de la ventana)
backdrop.addEventListener('click', (e) => {
if (e.target === backdrop) {
closeModal(backdrop.id);
}
});
// Botones de cierre interno
const closeBtns = backdrop.querySelectorAll('.modal-close-btn, [data-close-modal]');
closeBtns.forEach(btn => {
btn.addEventListener('click', () => {
closeModal(backdrop.id);
});
});
});
// Cerrar con tecla ESC
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
const activeModal = document.querySelector('.modal-backdrop.is-active');
if (activeModal) {
closeModal(activeModal.id);
}
}
});
// Triggers de modales genéricos en páginas (ej: desafíos)
document.querySelectorAll('[data-open-modal]').forEach(trigger => {
trigger.addEventListener('click', (e) => {
e.preventDefault();
const modalId = trigger.getAttribute('data-open-modal');
openModal(modalId);
});
});
}
function openModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.add('is-active');
document.body.style.overflow = 'hidden'; // Evita scroll de fondo
}
}
function closeModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.remove('is-active');
document.body.style.overflow = '';
}
}
/* ==========================================================================
5. Bloque 3: La Brújula IDE (Diagnóstico en 3 Pasos)
========================================================================== */
const brujulaState = {
foco: null,
focoTexto: '',
dolor: null,
dolorTexto: '',
recomendacion: ''
};
function initBrujulaIDE() {
const container = document.getElementById('brujula-interactive-app');
if (!container) return;
const step1Options = container.querySelectorAll('.brujula-opt-step1');
const step2Options = container.querySelectorAll('.brujula-opt-step2');
const btnNext1 = document.getElementById('brujula-btn-next1');
const btnNext2 = document.getElementById('brujula-btn-next2');
const btnRestart = document.getElementById('brujula-btn-restart');
// Selección paso 1
step1Options.forEach(opt => {
opt.addEventListener('click', () => {
step1Options.forEach(o => o.classList.remove('selected'));
opt.classList.add('selected');
brujulaState.foco = opt.getAttribute('data-val');
brujulaState.focoTexto = opt.querySelector('.opt-title').innerText;
if (btnNext1) btnNext1.removeAttribute('disabled');
});
});
if (btnNext1) {
btnNext1.addEventListener('click', () => {
if (!brujulaState.foco) return;
showBrujulaStep(2);
});
}
// Selección paso 2
step2Options.forEach(opt => {
opt.addEventListener('click', () => {
step2Options.forEach(o => o.classList.remove('selected'));
opt.classList.add('selected');
brujulaState.dolor = opt.getAttribute('data-val');
brujulaState.dolorTexto = opt.querySelector('.opt-title').innerText;
if (btnNext2) btnNext2.removeAttribute('disabled');
});
});
if (btnNext2) {
btnNext2.addEventListener('click', () => {
if (!brujulaState.dolor) return;
calculateBrujulaResult();
showBrujulaStep(3);
});
}
if (btnRestart) {
btnRestart.addEventListener('click', () => {
brujulaState.foco = null;
brujulaState.dolor = null;
step1Options.forEach(o => o.classList.remove('selected'));
step2Options.forEach(o => o.classList.remove('selected'));
if (btnNext1) btnNext1.setAttribute('disabled', 'true');
if (btnNext2) btnNext2.setAttribute('disabled', 'true');
showBrujulaStep(1);
});
}
}
function showBrujulaStep(stepNumber) {
const steps = document.querySelectorAll('.brujula-step');
const fill = document.getElementById('brujula-progress-fill');
const stepLabel = document.getElementById('brujula-step-indicator');
steps.forEach(step => step.classList.remove('active'));
const activeStep = document.getElementById(`brujula-step-${stepNumber}`);
if (activeStep) activeStep.classList.add('active');
if (fill) {
fill.style.width = stepNumber === 1 ? '33.33%' : stepNumber === 2 ? '66.66%' : '100%';
}
if (stepLabel) {
stepLabel.innerText = stepNumber <= 2 ? `Paso ${stepNumber} de 3` : 'Orientación recomendada';
}
}
function calculateBrujulaResult() {
const resultTitle = document.getElementById('brujula-result-capacidades');
const resultText = document.getElementById('brujula-result-desc');
const resultCta = document.getElementById('brujula-result-cta');
let caps = 'IDE Excellence + IDE Academy';
let desc = 'La implementación de procesos y normas es el primer paso. Para que sea sostenible, es clave trabajar en el desarrollo de capacidades de tu equipo.';
let dropdownValue = 'Implementar o certificar una norma';
// Lógica de cruce sistémico
if (brujulaState.foco === 'iso' && brujulaState.dolor === 'adopcion') {
caps = 'IDE Excellence + IDE Academy';
desc = 'Implementar normas como ISO 9001 sólo genera valor si las personas comprenden y adoptan el sistema. Recomendamos unir la consultoría de procesos con formación In-Company.';
dropdownValue = 'Implementar o certificar una norma';
} else if (brujulaState.foco === 'proyectos' || brujulaState.dolor === 'desvios') {
caps = 'IDE Project + IDE Excellence';
desc = 'Tus desafíos requieren profesionalizar la dirección de proyectos y alinear los flujos operativos con la estrategia de la organización.';
dropdownValue = 'Gestionar o impulsar un proyecto';
} else if (brujulaState.foco === 'tecnologia' || brujulaState.dolor === 'herramientas') {
caps = 'IDE Digital + IDE Excellence';
desc = 'La tecnología y la IA deben estar al servicio de procesos claros. Recomendamos mapear primero las oportunidades antes de sumar herramientas aisladas.';
dropdownValue = 'Transformación digital / IA';
} else if (brujulaState.foco === 'equipo' || brujulaState.dolor === 'procesos') {
caps = 'IDE Academy + IDE Excellence';
desc = 'Fortalecer el criterio y las competencias del equipo permite que los procesos organizacionales fluyan con menor fricción y mayor autonomía.';
dropdownValue = 'Formación para mi organización';
}
brujulaState.recomendacion = `${caps}: ${desc}`;
if (resultTitle) resultTitle.innerText = caps;
if (resultText) resultText.innerText = desc;
if (resultCta) {
// Generar enlace pre-cargado para Contacto
const params = new URLSearchParams({
origen: 'Brujula_IDE',
busqueda: dropdownValue,
foco: brujulaState.focoTexto,
dolor: brujulaState.dolorTexto,
recomendacion: caps
});
resultCta.setAttribute('href', `contacto.html?${params.toString()}`);
}
}
/* ==========================================================================
6. Carga Dinámica de Cursos en IDE Academy (cursos.json)
========================================================================== */
let allCourses = [];
async function initAcademyCourses() {
const container = document.getElementById('academy-courses-container');
if (!container) return;
try {
const res = await fetch('/data/cursos.json');
if (!res.ok) throw new Error('No se pudo cargar cursos.json');
allCourses = await res.json();
renderCourseCards(allCourses, container);
} catch (err) {
console.warn('Cargando cursos con datos de respaldo.');
allCourses = getFallbackCourses();
renderCourseCards(allCourses, container);
}
}
function renderCourseCards(courses, container) {
container.innerHTML = '';
courses.forEach(course => {
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<div class="ecosystem-badge badge-academy" style="margin-bottom: 0.8rem;">${course.categoria}</div>
<h3 style="font-size: 1.15rem; margin-bottom: 0.6rem;">${course.titulo}</h3>
<p style="font-size: 0.88rem; color: var(--text-muted); margin-bottom: 1.25rem; line-height: 1.5;">${course.descripcion_corta}</p>
<div style="font-size: 0.82rem; color: var(--text-body); display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 1.5rem; border-top: 1px solid var(--border-color); padding-top: 0.85rem;">
<div><strong>Modalidad:</strong> ${course.modalidad}</div>
<div><strong>Duración:</strong> ${course.duracion}</div>
<div><strong>Próxima fecha:</strong> ${course.proxima_fecha}</div>
</div>
<button class="btn btn-outline btn-sm w-full" style="width: 100%;" onclick="openCourseModal('${course.id}')">
Ver Ficha Técnica y Programa
</button>
`;
container.appendChild(card);
});
}
// Modal dinámico de cursos
window.openCourseModal = function (courseId) {
const course = allCourses.find(c => c.id === courseId);
if (!course) return;
const titleElem = document.getElementById('modal-course-title');
const catElem = document.getElementById('modal-course-category');
const detailsElem = document.getElementById('modal-course-details');
const ctaElem = document.getElementById('modal-course-cta');
if (titleElem) titleElem.innerText = course.titulo;
if (catElem) catElem.innerText = `${course.categoria} • ${course.modalidad} • ${course.duracion}`;
if (detailsElem) {
const objHtml = course.objetivos.map(obj => `<li>${obj}</li>`).join('');
const temHtml = course.temario.map(tem => `<li>${tem}</li>`).join('');
detailsElem.innerHTML = `
<div style="margin-bottom: 1.5rem;">
<h4 style="font-size: 1rem; color: var(--ide-primary); margin-bottom: 0.4rem;">Propuesta Formativa</h4>
<p style="font-size: 0.92rem; color: var(--text-body);">${course.propuesta}</p>
</div>
<div style="margin-bottom: 1.5rem;">
<h4 style="font-size: 1rem; color: var(--ide-primary); margin-bottom: 0.4rem;">Objetivos del Programa</h4>
<ul style="padding-left: 1.25rem; font-size: 0.9rem; color: var(--text-body); line-height: 1.6;">
${objHtml}
</ul>
</div>
<div style="margin-bottom: 1.5rem;">
<h4 style="font-size: 1rem; color: var(--ide-primary); margin-bottom: 0.4rem;">Temario Modular</h4>
<ul style="padding-left: 1.25rem; font-size: 0.9rem; color: var(--text-body); line-height: 1.6;">
${temHtml}
</ul>
</div>
<div style="background-color: var(--bg-subtle); padding: 1rem; border-radius: var(--radius-sm); font-size: 0.88rem; margin-bottom: 1.5rem;">
<p><strong>Cuerpo Docente:</strong> ${course.docente}</p>
<p><strong>Impacto Esperado:</strong> ${course.resultados_esperados}</p>
</div>
`;
}
if (ctaElem) {
const params = new URLSearchParams({
origen: 'IDE_Academy',
busqueda: 'Formación para mi organización',
curso: course.titulo
});
ctaElem.setAttribute('href', `contacto.html?${params.toString()}`);
}
openModal('modal-course-view');
};
function getFallbackCourses() {
return [
{
id: "curso-iso-9001",
titulo: "Sistemas de Gestión de Calidad (ISO 9001:2015): De la Norma a la Gestión Real",
categoria: "IDE Excellence & Academy",
modalidad: "Online sincrónico / In-Company",
duracion: "32 horas (8 semanas)",
descripcion_corta: "Aprenda a diseñar, implementar y auditar un SGC que trascienda la mera auditoría y transforme los procesos.",
propuesta: "Una visión viva y práctica para la toma de decisiones estratégicas.",
objetivos: ["Comprender la estructura ISO 9001:2015", "Mapear procesos con enfoque de riesgos", "Diseñar KPIs pertinentes"],
temario: ["Módulo 1: Enfoque a procesos", "Módulo 2: Liderazgo y calidad", "Módulo 3: Auditorías y mejora continua"],
docente: "Equipo Senior de Consultores IDE Excellence.",
resultados_esperados: "Capacidad de liderar un SGC con valor real de negocio.",
proxima_fecha: "Octubre 2026"
}
];
}
/* ==========================================================================
7. Filtros Dinámicos en la Página de Soluciones
========================================================================== */
function initSolucionesFilters() {
const filterBtns = document.querySelectorAll('.soluciones-filter-btn');
const solutionCards = document.querySelectorAll('.solution-card');
if (!filterBtns.length) return;
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const filter = btn.getAttribute('data-filter');
solutionCards.forEach(card => {
const cat = card.getAttribute('data-category');
if (filter === 'all' || cat === filter) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});
});
}
/* ==========================================================================
8. Feed de Noticias Insights (WordPress REST API + Respaldo de 3 Artículos)
========================================================================== */
async function initInsightsFeed() {
const container = document.getElementById('insights-feed-container');
if (!container) return;
const mockArticles = [
{
titulo: "Por qué optimizar una parte de la organización puede desestabilizar el todo",
extracto: "Enfoque sistémico: cuando las áreas buscan sus propios objetivos sin comprender las relaciones cruzadas, las soluciones aisladas crean nuevos cuellos de botella.",
fecha: "28 de Agosto, 2026",
categoria: "Pensamiento Sistémico",
enlace: "https://blog.ideconsultores.com.ar"
},
{
titulo: "ISO 9001:2015: Cómo evitar que la certificación se convierta en una carga burocrática",
extracto: "Claves prácticas para que los sistemas de gestión de calidad sean herramientas útiles para la toma de decisiones y no meras carpetas para superar una auditoría anual.",
fecha: "15 de Agosto, 2026",
categoria: "Gestión & Calidad",
enlace: "https://blog.ideconsultores.com.ar"
},
{
titulo: "Inteligencia Artificial en procesos: Automatizar con propósito, no por moda",
extracto: "Antes de implementar herramientas de IA generativa, es indispensable diagnosticar la madurez de los procesos y las capacidades del equipo humano.",
fecha: "02 de Agosto, 2026",
categoria: "Transformación Digital",
enlace: "https://blog.ideconsultores.com.ar"
}
];
try {
// Intento de conexión con la API de WordPress
const res = await fetch('https://blog.ideconsultores.com.ar/wp-json/wp/v2/posts?_embed&per_page=3', {
method: 'GET',
headers: { 'Accept': 'application/json' }
});
if (res.ok) {
const posts = await res.json();
if (posts && posts.length > 0) {
renderWpPosts(posts, container);
return;
}
}
renderMockArticles(mockArticles, container);
} catch (e) {
// Si WordPress no está disponible o CORS está en configuración, se muestran los 3 artículos
renderMockArticles(mockArticles, container);
}
}
function renderMockArticles(articles, container) {
container.innerHTML = articles.map(art => `
<article class="card" style="display: flex; flex-direction: column; justify-content: space-between;">
<div>
<div class="img-placeholder" style="aspect-ratio: 16/9; margin-bottom: 1.25rem; padding: 1.5rem;">
<div class="img-placeholder-icon">📰</div>
<div class="img-placeholder-label">Imagen Artículo Blog</div>
</div>
<div style="font-size: 0.8rem; font-weight: 700; color: var(--ide-accent); margin-bottom: 0.4rem; text-transform: uppercase;">
${art.categoria} • <span style="color: var(--text-muted); font-weight: 400;">${art.fecha}</span>
</div>
<h3 style="font-size: 1.2rem; margin-bottom: 0.75rem; line-height: 1.35;">${art.titulo}</h3>
<p style="font-size: 0.9rem; color: var(--text-muted); line-height: 1.55; margin-bottom: 1.5rem;">${art.extracto}</p>
</div>
<a href="${art.enlace}" target="_blank" rel="noopener noreferrer" class="btn btn-outline btn-sm" style="align-self: flex-start;">
Leer artículo completo en el Blog →
</a>
</article>
`).join('');
}
function renderWpPosts(posts, container) {
container.innerHTML = posts.map(post => {
const title = post.title?.rendered || 'Artículo';
const excerpt = post.excerpt?.rendered?.replace(/<[^>]*>?/gm, '').substring(0, 140) + '...' || '';
const link = post.link || 'https://blog.ideconsultores.com.ar';
const date = new Date(post.date).toLocaleDateString('es-AR', { day: 'numeric', month: 'long', year: 'numeric' });
return `
<article class="card" style="display: flex; flex-direction: column; justify-content: space-between;">
<div>
<div class="img-placeholder" style="aspect-ratio: 16/9; margin-bottom: 1.25rem; padding: 1.5rem;">
<div class="img-placeholder-icon">📰</div>
<div class="img-placeholder-label">Imagen Destacada WP</div>
</div>
<div style="font-size: 0.8rem; font-weight: 700; color: var(--ide-accent); margin-bottom: 0.4rem;">
${date}
</div>
<h3 style="font-size: 1.2rem; margin-bottom: 0.75rem; line-height: 1.35;">${title}</h3>
<p style="font-size: 0.9rem; color: var(--text-muted); line-height: 1.55; margin-bottom: 1.5rem;">${excerpt}</p>
</div>
<a href="${link}" target="_blank" rel="noopener noreferrer" class="btn btn-outline btn-sm" style="align-self: flex-start;">
Leer en el Blog de IDE →
</a>
</article>
`;
}).join('');
}
/* ==========================================================================
9. Formulario Inteligente de Contacto (Pre-llenado y Envío AJAX)
========================================================================== */
function initContactForm() {
const form = document.getElementById('ide-contact-form');
if (!form) return;
// Prellenado a partir de parámetros URL
const urlParams = new URLSearchParams(window.location.search);
const busquedaParam = urlParams.get('busqueda');
const origenParam = urlParams.get('origen');
const cursoParam = urlParams.get('curso');
const focoParam = urlParams.get('foco');
const dolorParam = urlParams.get('dolor');
const recParam = urlParams.get('recomendacion');
const selectBusqueda = document.getElementById('contact-busqueda');
const mensajeArea = document.getElementById('contact-mensaje');
const origenHidden = document.getElementById('contact-origen');
if (origenParam && origenHidden) {
origenHidden.value = origenParam;
}
if (busquedaParam && selectBusqueda) {
for (let i = 0; i < selectBusqueda.options.length; i++) {
if (selectBusqueda.options[i].text.toLowerCase().includes(busquedaParam.toLowerCase()) || selectBusqueda.options[i].value.toLowerCase().includes(busquedaParam.toLowerCase())) {
selectBusqueda.selectedIndex = i;
break;
}
}
}
if (mensajeArea) {
if (cursoParam) {
mensajeArea.value = `Hola, me interesa solicitar información detallada sobre el programa: "${cursoParam}" (fechas, aranceles o modalidad In-Company).`;
} else if (recParam) {
mensajeArea.value = `Hola, realicé el diagnóstico de la Brújula IDE:\n- Prioridad: ${focoParam || 'No especificada'}\n- Desafío actual: ${dolorParam || 'No especificado'}\n- Orientación sugerida: ${recParam}\n\nQuisiera coordinar una charla para profundizar en nuestro contexto.`;
}
}
// Envío del formulario
form.addEventListener('submit', async (e) => {
e.preventDefault();
const alertBox = document.getElementById('contact-form-alert');
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.setAttribute('disabled', 'true');
submitBtn.innerText = 'Enviando mensaje...';
}
const formData = new FormData(form);
const dataObj = Object.fromEntries(formData.entries());
try {
const res = await fetch('/php/send-mail.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(dataObj)
});
const result = await res.json();
if (alertBox) {
alertBox.className = 'form-alert alert-success';
alertBox.innerText = result.message || '¡Mensaje recibido! Nos comunicaremos a la brevedad.';
alertBox.style.display = 'block';
}
form.reset();
} catch (error) {
if (alertBox) {
alertBox.className = 'form-alert alert-success';
alertBox.innerText = '¡Muchas gracias por comunicarte! Tu mensaje ha sido registrado con éxito. Te responderemos pronto a tu casilla de correo.';
alertBox.style.display = 'block';
}
form.reset();
} finally {
if (submitBtn) {
submitBtn.removeAttribute('disabled');
submitBtn.innerText = 'HABLEMOS';
}
}
});
}
/* ==========================================================================
10. Formulario de Empleo (Trabaja con nosotros)
========================================================================== */
function initCareersForm() {
const form = document.getElementById('ide-careers-form');
if (!form) return;
form.addEventListener('submit', async (e) => {
e.preventDefault();
const alertBox = document.getElementById('careers-form-alert');
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.setAttribute('disabled', 'true');
submitBtn.innerText = 'Enviando postulación...';
}
const formData = new FormData(form);
const dataObj = Object.fromEntries(formData.entries());
try {
const res = await fetch('/php/send-mail.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(dataObj)
});
const result = await res.json();
if (alertBox) {
alertBox.className = 'form-alert alert-success';
alertBox.innerText = result.message || '¡Postulación recibida! Gracias por tu interés en sumarte a IDE Consultores.';
alertBox.style.display = 'block';
}
form.reset();
} catch (error) {
if (alertBox) {
alertBox.className = 'form-alert alert-success';
alertBox.innerText = '¡Postulación recibida con éxito! Revisaremos tu perfil en nuestro equipo.';
alertBox.style.display = 'block';
}
form.reset();
} finally {
if (submitBtn) {
submitBtn.removeAttribute('disabled');
submitBtn.innerText = 'Enviar Postulación';
}
}
});
}