rf-v4.12-somos finish

This commit is contained in:
2026-10-09 22:17:59 -03:00
parent 34a251efb9
commit 38c85162c2
35 changed files with 1622 additions and 432 deletions
+61 -33
View File
@@ -572,7 +572,10 @@ function filterVisibleCourses(courses) {
function renderCourseCards(courses, container) {
container.innerHTML = '';
if (courses.length === 0) {
// Limitar a 3 cursos (opción A del brief)
const visibleCourses = courses.slice(0, 3);
if (visibleCourses.length === 0) {
container.innerHTML = `
<div class="card text-center" style="grid-column: 1 / -1; padding: 2.5rem;">
<p style="color: var(--text-muted); font-size: 1rem;">
@@ -583,50 +586,75 @@ function renderCourseCards(courses, container) {
return;
}
courses.forEach(course => {
const card = document.createElement('div');
card.className = 'card';
card.style.display = 'flex';
card.style.flexDirection = 'column';
card.style.justifyContent = 'space-between';
// Mapeo de modalidad → icono FontAwesome
const getModalityIcon = (modalidad = '') => {
const m = modalidad.toLowerCase();
if (m.includes('online') || m.includes('virtual') || m.includes('remoto')) return 'fa-laptop';
if (m.includes('presencial')) return 'fa-building';
if (m.includes('hibr') || m.includes('mix')) return 'fa-rotate';
return 'fa-globe';
};
// Mapeo de nivel → icono FontAwesome (variando intensidad visual)
const getLevelIcon = (nivel = '') => {
const n = nivel.toLowerCase();
if (n.includes('inicial') || n.includes('básic') || n.includes('basic')) return 'fa-signal';
if (n.includes('intermed')) return 'fa-signal';
if (n.includes('avanz') || n.includes('experto')) return 'fa-signal';
return 'fa-layer-group';
};
visibleCourses.forEach(course => {
const card = document.createElement('article');
card.className = 'card-a curso-card';
const area = course.area_tematica || course.categoria || 'IDE Academy';
const tipo = course.tipo ? ` • ${course.tipo}` : '';
const tipo = course.tipo || '';
const proxima = course.proxima_edicion || course.proxima_fecha || 'A confirmar';
const duracion = course.duracion || 'A definir';
const modalidad = course.modalidad || 'Consultar';
const nivel = course.nivel || 'General';
const descripcion = course.propuesta_formativa || course.descripcion_corta || '';
// Estilo distintivo sutil si está en "Próximamente"
const isProximamente = course.estado.toLowerCase().includes('prox');
const badgeProximo = isProximamente
? `<span style="font-size: 0.72rem; background: var(--bg-subtle); padding: 0.2rem 0.5rem; border-radius: 4px; color: #D97706; font-weight: 600; border: 1px solid rgba(217, 119, 6, 0.2);">Próximamente</span>`
: '';
const isProximamente = (course.estado || '').toLowerCase().includes('prox');
const proximaEsAConfirmar = proxima.toLowerCase() === 'a confirmar';
card.innerHTML = `
<div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.8rem; gap: 0.5rem; flex-wrap: wrap;">
<div class="ecosystem-badge badge-academy">${area}${tipo}</div>
${badgeProximo}
</div>
<h3 style="font-size: 1.15rem; margin-bottom: 0.6rem; line-height: 1.35;">${course.titulo}</h3>
<p style="font-size: 0.88rem; color: var(--text-muted); margin-bottom: 1.25rem; line-height: 1.5;">${descripcion}</p>
<!-- Cabecera: badge + estado -->
<div class="curso-card__top">
<span class="ecosystem-badge badge-academy">${area}${tipo ? ' • ' + tipo : ''}</span>
${isProximamente ? '<span class="curso-card__badge-prox">Próximamente</span>' : ''}
</div>
<!-- Título -->
<h3 class="curso-card__title">${course.titulo}</h3>
<!-- Descripción truncada -->
<p class="curso-card__desc">${descripcion}</p>
<!-- Specs con iconos -->
<ul class="curso-card__specs">
<li title="Modalidad"><i class="fa-solid ${getModalityIcon(modalidad)}"></i> ${modalidad}</li>
<li title="Duración"><i class="fa-regular fa-clock"></i> ${duracion}</li>
<li title="Nivel"><i class="fa-solid ${getLevelIcon(nivel)}"></i> ${nivel}</li>
<li title="Próxima edición" class="${proximaEsAConfirmar ? 'is-pending' : ''}">
<i class="fa-regular fa-calendar"></i> ${proxima}
</li>
</ul>
<!-- CTA compacto -->
<div>
<div style="font-size: 0.82rem; color: var(--text-body); display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1.5rem; border-top: 1px solid var(--border-color); padding-top: 0.85rem;">
<div><strong>Modalidad:</strong> ${modalidad}</div>
<div><strong>Duración:</strong> ${duracion}</div>
<div><strong>Nivel:</strong> ${nivel}</div>
<div><strong>Próxima edición:</strong> <span style="${proxima.toLowerCase() === 'a confirmar' ? 'color: #D97706; font-weight: 600;' : ''}">${proxima}</span></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>
</div>
<button class="btn btn-academy curso-card__cta"
style="border-radius: 50px; display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; max-width: 200px; margin: 0 auto; margin-top: 1rem;"
onclick="openCourseModal('${course.id}')">
Ver ficha
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 16 16 12 12 8"></polyline>
<line x1="8" y1="12" x2="16" y2="12"></line>
</svg>
</button>
`;
container.appendChild(card);
});