727 lines
28 KiB
JavaScript
727 lines
28 KiB
JavaScript
/**
|
|
* 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';
|
|
}
|
|
}
|
|
});
|
|
} |