// pages/Blog.jsx — listado de todos los artículos con filtro y buscador const PAGE_SIZE = 10; function BlogPage({ articles, loading, onOpenArticle, density, search, onSearch }) { const [category, setCategory] = React.useState('Todos'); const [page, setPage] = React.useState(1); const filtered = articles.filter((a) => { if (category !== 'Todos' && a.category !== category) return false; if (search) { const q = search.toLowerCase(); if (!a.title.toLowerCase().includes(q) && !a.excerpt.toLowerCase().includes(q)) return false; } return true; }); const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE)); const safePage = Math.min(page, totalPages); const paginated = filtered.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE); // Resetear a página 1 cuando cambian filtros React.useEffect(() => { setPage(1); }, [category, search]); const goTo = (p) => { setPage(p); window.scrollTo({ top: 0, behavior: 'smooth' }); }; // Generar array de páginas con elipsis: [1, …, 4, 5, 6, …, 12] const pageNumbers = () => { if (totalPages <= 7) return Array.from({ length: totalPages }, (_, i) => i + 1); const pages = new Set([1, totalPages, safePage, safePage - 1, safePage + 1].filter(p => p >= 1 && p <= totalPages)); return [...pages].sort((a, b) => a - b); }; return ( <>
Blog

Todos los artículos

Notas de campo, casos de éxito, comparativas de herramientas y lo que voy aprendiendo montando IA y automatizaciones.

{window.CATEGORIES.map((c) => )}
onSearch(e.target.value)} />
{filtered.length} {filtered.length === 1 ? 'artículo' : 'artículos'} {search && que coinciden con "{search}"} {category !== 'Todos' && en {category}} {totalPages > 1 && · Página {safePage} de {totalPages}}
{loading ?

Cargando artículos…

: filtered.length === 0 ?

{articles.length === 0 ? 'Aún no hay artículos publicados.' : 'Nada por aquí. Prueba a quitar el filtro o cambiar la búsqueda.'}

:
{paginated.map((a) => )}
} {totalPages > 1 && !loading && ( )}
); } window.BlogPage = BlogPage;