252 lines
10 KiB
JavaScript
252 lines
10 KiB
JavaScript
document.addEventListener('DOMContentLoaded', async () => {
|
|
const GHOST_API_URL = 'https://blog.amoryroma.com.ar';
|
|
const GHOST_API_KEY = '82450ba91ca6b5b9628006eec4';
|
|
|
|
// Elementos del DOM
|
|
const featuredSection = document.getElementById('featured-posts');
|
|
const featuredGrid = document.getElementById('featured-grid');
|
|
const blogGrid = document.getElementById('blog-grid');
|
|
const loadMoreBtn = document.getElementById('load-more');
|
|
const resultsCount = document.getElementById('results-count');
|
|
const emptyState = document.getElementById('empty-state');
|
|
const gridSectionTitle = document.getElementById('grid-section-title');
|
|
const gridSectionSubtitle = document.getElementById('grid-section-subtitle');
|
|
|
|
// Estado de los filtros
|
|
let posts = [];
|
|
let state = {
|
|
category: 'all',
|
|
filter: 'all', // 'all' o 'destacados'
|
|
search: '',
|
|
sort: 'recent'
|
|
};
|
|
|
|
// Cargar artículos desde Ghost API
|
|
async function loadPosts() {
|
|
try {
|
|
const response = await fetch(`${GHOST_API_URL}/ghost/api/content/posts/?key=${GHOST_API_KEY}&limit=all&include=tags,authors`);
|
|
const data = await response.json();
|
|
|
|
posts = data.posts.map(post => ({
|
|
id: post.id,
|
|
slug: post.slug,
|
|
titulo: post.title,
|
|
extracto: post.excerpt,
|
|
categoria: post.primary_tag ? post.primary_tag.name.toLowerCase() : 'general',
|
|
tags: post.tags ? post.tags.map(t => t.name.toLowerCase()) : [],
|
|
imagen: post.feature_image || 'assets/blog/default.jpg',
|
|
fecha: post.published_at,
|
|
tiempo_lectura: Math.ceil(post.reading_time) || 5,
|
|
destacado: post.featured
|
|
}));
|
|
|
|
renderPosts();
|
|
setupEventListeners();
|
|
} catch (error) {
|
|
console.error('Error cargando posts de Ghost:', error);
|
|
if(emptyState) {
|
|
emptyState.style.display = 'block';
|
|
emptyState.querySelector('h3').textContent = 'Error al cargar el blog';
|
|
emptyState.querySelector('p').textContent = 'Por favor, recarga la página.';
|
|
}
|
|
}
|
|
}
|
|
|
|
function formatDate(dateString) {
|
|
const options = { day: '2-digit', month: 'short', year: 'numeric' };
|
|
return new Date(dateString).toLocaleDateString('es-AR', options);
|
|
}
|
|
|
|
function createCard(post, isFeatured = false) {
|
|
const catFormatted = post.categoria.charAt(0).toUpperCase() + post.categoria.slice(1);
|
|
const cardClass = isFeatured ? 'featured-card' : 'blog-card';
|
|
const badge = isFeatured && post.destacado ? '<span class="featured-badge">Destacado</span>' : '';
|
|
const metaClass = isFeatured ? 'featured-meta' : 'card-meta';
|
|
const titleClass = isFeatured ? 'featured-title' : 'card-title';
|
|
const excerptClass = isFeatured ? 'featured-excerpt' : 'card-excerpt';
|
|
const linkClass = isFeatured ? 'btn-read' : 'card-link';
|
|
const linkText = isFeatured ? 'Leer artículo →' : 'Leer artículo';
|
|
|
|
return `
|
|
<article class="${cardClass}" data-categories="${post.categoria}" data-featured="${post.destacado}">
|
|
<div class="${isFeatured ? 'featured-image' : 'card-image'}">
|
|
<img src="${post.imagen}" alt="${post.titulo}" loading="lazy">
|
|
${!isFeatured ? `<span class="card-category ${post.categoria}">${catFormatted}</span>` : ''}
|
|
${badge}
|
|
</div>
|
|
<div class="${isFeatured ? 'featured-content' : 'card-content'}">
|
|
<div class="${metaClass}">
|
|
<span class="category-tag ${post.categoria}">${catFormatted}</span>
|
|
<time datetime="${post.fecha}">${formatDate(post.fecha)}</time>
|
|
</div>
|
|
<h3 class="${titleClass}">${post.titulo}</h3>
|
|
<p class="${excerptClass}">${post.extracto}</p>
|
|
<div class="${isFeatured ? 'featured-footer' : ''}">
|
|
${isFeatured ? `<span class="reading-time">⏱ ${post.tiempo_lectura} min</span>` : `<span class="reading-time-mini">${post.tiempo_lectura} min</span>`}
|
|
<a href="${GHOST_API_URL}/${post.slug}/" class="${linkClass}" target="_blank">${linkText}</a>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
`;
|
|
}
|
|
|
|
function renderPosts() {
|
|
// 1. FILTRAR
|
|
let filtered = posts.filter(post => {
|
|
const matchCategory = state.category === 'all' || post.categoria === state.category;
|
|
const matchFilter = state.filter === 'all' || (state.filter === 'destacados' && post.destacado);
|
|
const q = state.search.toLowerCase();
|
|
const matchSearch = !q ||
|
|
post.titulo.toLowerCase().includes(q) ||
|
|
post.extracto.toLowerCase().includes(q) ||
|
|
post.tags.some(tag => tag.includes(q));
|
|
|
|
return matchCategory && matchFilter && matchSearch;
|
|
});
|
|
|
|
// 2. ORDENAR
|
|
if (state.sort === 'recent') {
|
|
filtered.sort((a, b) => new Date(b.fecha) - new Date(a.fecha));
|
|
} else if (state.sort === 'popular') {
|
|
// Como la API pública de Ghost no expone "vistas", simulamos popularidad poniendo los destacados primero
|
|
filtered.sort((a, b) => (b.destacado === a.destacado) ? 0 : b.destacado ? 1 : -1);
|
|
}
|
|
|
|
// 3. DECIDIR VISTA: ¿Es la vista por defecto (sin filtros)?
|
|
const isDefaultView = state.category === 'all' && state.filter === 'all' && state.search === '';
|
|
|
|
if (isDefaultView) {
|
|
// VISTA POR DEFECTO: Mostrar Destacados + Últimos 3
|
|
if (featuredSection) featuredSection.style.display = 'block';
|
|
if (gridSectionTitle) gridSectionTitle.textContent = 'Últimos artículos';
|
|
if (gridSectionSubtitle) gridSectionSubtitle.textContent = 'Lo más nuevo y a la vanguardia.';
|
|
if (loadMoreBtn) {
|
|
loadMoreBtn.style.display = 'inline-block';
|
|
loadMoreBtn.textContent = 'Ver todos los artículos en el Blog';
|
|
loadMoreBtn.onclick = () => window.location.href = `${GHOST_API_URL}/`;
|
|
}
|
|
|
|
const featuredPosts = filtered.filter(p => p.destacado).slice(0, 3);
|
|
const latestPosts = filtered.slice(0, 3);
|
|
|
|
if (featuredGrid) featuredGrid.innerHTML = featuredPosts.map(p => createCard(p, true)).join('');
|
|
if (blogGrid) blogGrid.innerHTML = latestPosts.map(p => createCard(p, false)).join('');
|
|
|
|
if (resultsCount) resultsCount.innerHTML = `Mostrando los <strong>últimos 3</strong> artículos`;
|
|
if (emptyState) emptyState.style.display = 'none';
|
|
|
|
} else {
|
|
// VISTA FILTRADA: Ocultar Destacados, mostrar TODOS los resultados en la grilla principal
|
|
if (featuredSection) featuredSection.style.display = 'none';
|
|
if (loadMoreBtn) loadMoreBtn.style.display = 'none'; // Ocultamos "cargar más" porque ya mostramos todos los filtrados
|
|
|
|
// Actualizar títulos según el filtro
|
|
if (gridSectionTitle) {
|
|
if (state.search) gridSectionTitle.textContent = `Resultados de búsqueda`;
|
|
else if (state.category !== 'all') gridSectionTitle.textContent = `Artículos de ${state.category.charAt(0).toUpperCase() + state.category.slice(1)}`;
|
|
else if (state.filter === 'destacados') gridSectionTitle.textContent = `Artículos Destacados`;
|
|
}
|
|
if (gridSectionSubtitle) gridSectionSubtitle.textContent = `Se encontraron ${filtered.length} artículo${filtered.length !== 1 ? 's' : ''}`;
|
|
|
|
if (blogGrid) {
|
|
if (filtered.length === 0) {
|
|
blogGrid.innerHTML = '';
|
|
if (emptyState) {
|
|
emptyState.style.display = 'block';
|
|
emptyState.querySelector('h3').textContent = 'No encontramos artículos con esos filtros';
|
|
}
|
|
} else {
|
|
if (emptyState) emptyState.style.display = 'none';
|
|
// Mostramos TODOS los artículos que coinciden con el filtro, no solo 3
|
|
blogGrid.innerHTML = filtered.map(p => createCard(p, false)).join('');
|
|
}
|
|
}
|
|
|
|
if (resultsCount) {
|
|
resultsCount.innerHTML = `Mostrando <strong>${filtered.length}</strong> artículo${filtered.length !== 1 ? 's' : ''}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
function setupEventListeners() {
|
|
// 1. Botones de Categoría
|
|
document.querySelectorAll('.category-btn').forEach(btn => {
|
|
btn.addEventListener('click', (e) => {
|
|
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
|
e.target.classList.add('active');
|
|
state.category = e.target.dataset.category;
|
|
renderPosts();
|
|
});
|
|
});
|
|
|
|
// 2. Botones de Filtro (Todos / Destacados)
|
|
document.querySelectorAll('.filter-btn').forEach(btn => {
|
|
btn.addEventListener('click', (e) => {
|
|
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
e.target.classList.add('active');
|
|
state.filter = e.target.dataset.filter;
|
|
renderPosts();
|
|
});
|
|
});
|
|
|
|
// 3. Buscador
|
|
const searchInput = document.getElementById('blog-search');
|
|
const searchClear = document.getElementById('search-clear');
|
|
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', (e) => {
|
|
state.search = e.target.value;
|
|
if (searchClear) searchClear.classList.toggle('visible', state.search.length > 0);
|
|
renderPosts();
|
|
});
|
|
}
|
|
|
|
if (searchClear) {
|
|
searchClear.addEventListener('click', () => {
|
|
if (searchInput) {
|
|
searchInput.value = '';
|
|
state.search = '';
|
|
searchClear.classList.remove('visible');
|
|
searchInput.focus();
|
|
renderPosts();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 4. Ordenamiento
|
|
const sortSelect = document.getElementById('sort-select');
|
|
if (sortSelect) {
|
|
sortSelect.addEventListener('change', (e) => {
|
|
state.sort = e.target.value;
|
|
renderPosts();
|
|
});
|
|
}
|
|
|
|
// 5. Botón Limpiar Filtros
|
|
const resetBtn = document.getElementById('reset-filters');
|
|
const emptyReset = document.getElementById('empty-reset');
|
|
|
|
function resetAll() {
|
|
state = { category: 'all', filter: 'all', search: '', sort: 'recent' };
|
|
|
|
// Resetear UI
|
|
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
|
document.querySelector('.category-btn[data-category="all"]').classList.add('active');
|
|
|
|
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
document.querySelector('.filter-btn[data-filter="all"]').classList.add('active');
|
|
|
|
if (searchInput) searchInput.value = '';
|
|
if (searchClear) searchClear.classList.remove('visible');
|
|
if (sortSelect) sortSelect.value = 'recent';
|
|
|
|
renderPosts();
|
|
}
|
|
|
|
if (resetBtn) resetBtn.addEventListener('click', resetAll);
|
|
if (emptyReset) emptyReset.addEventListener('click', resetAll);
|
|
}
|
|
|
|
// Iniciar
|
|
await loadPosts();
|
|
}); |