Update con apartado de post y post de ejemplo
This commit is contained in:
213
src/layouts/ListadoPosts.astro
Normal file
213
src/layouts/ListadoPosts.astro
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
// ListadoPosts.astro
|
||||
const posts = await Astro.glob("../pages/posts/*.mdx");
|
||||
|
||||
// Función para ordenar posts
|
||||
const orderPosts = (posts, orderBy = "fecha", ascending = false) => {
|
||||
return [...posts].sort((a, b) => {
|
||||
if (orderBy === "fecha") {
|
||||
const comparison = new Date(b.frontmatter.fecha).getTime() -
|
||||
new Date(a.frontmatter.fecha).getTime();
|
||||
return ascending ? -comparison : comparison;
|
||||
} else if (orderBy === "titulo") {
|
||||
const comparison = a.frontmatter.titulo.localeCompare(b.frontmatter.titulo);
|
||||
return ascending ? comparison : -comparison;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
// Ordenar posts por defecto (más reciente primero)
|
||||
const initialPosts = orderPosts(posts, "fecha", false);
|
||||
---
|
||||
|
||||
<div class="container py-5">
|
||||
<div class="text-center mb-5 mt-3">
|
||||
<h1 class="display-4">Blog Ecobjetivos</h1>
|
||||
<p class="lead text-muted">Explora nuestros artículos sobre sostenibilidad y desarrollo</p>
|
||||
</div>
|
||||
|
||||
<!-- Controles de búsqueda y ordenamiento -->
|
||||
<div class="row justify-content-center mb-5">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-7">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-white">
|
||||
<i class="fas fa-search text-muted"></i>
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
id="searchInput"
|
||||
class="form-control border-start-0"
|
||||
placeholder="Buscar artículos..."
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<select id="orderSelect" class="form-select">
|
||||
<option value="fecha-desc">Más recientes primero</option>
|
||||
<option value="fecha-asc">Más antiguos primero</option>
|
||||
<option value="titulo-asc">Título A-Z</option>
|
||||
<option value="titulo-desc">Título Z-A</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Grid de posts -->
|
||||
<div class="row justify-content-center" id="postsContainer">
|
||||
{
|
||||
initialPosts.map((post) => (
|
||||
<div class="col-md-8 mb-4 post-item">
|
||||
<article class="card shadow-sm h-100 border-0">
|
||||
<div class="row g-0">
|
||||
<div class="col-md-4">
|
||||
{post.frontmatter.imagen ? (
|
||||
<img
|
||||
src={post.frontmatter.imagen}
|
||||
class="post-image rounded-start"
|
||||
alt={post.frontmatter.titulo}
|
||||
/>
|
||||
) : (
|
||||
<div class="default-image rounded-start">
|
||||
<i class="fas fa-leaf fa-3x text-success"></i>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card-body d-flex flex-column h-100">
|
||||
<div class="mb-3">
|
||||
<h2 class="card-title h4">
|
||||
{post.frontmatter.titulo}
|
||||
</h2>
|
||||
<p class="card-text text-muted">
|
||||
{post.frontmatter.descripcion}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-auto">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="author-info">
|
||||
<small class="text-muted d-block">
|
||||
<i class="fas fa-user-edit me-2"></i>
|
||||
{post.frontmatter.autor}
|
||||
</small>
|
||||
<small class="text-muted d-block">
|
||||
<i class="far fa-calendar-alt me-2"></i>
|
||||
{new Date(post.frontmatter.fecha).toLocaleDateString('es-ES', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</small>
|
||||
</div>
|
||||
<a href={post.url} class="btn btn-outline-success">
|
||||
Leer más
|
||||
<i class="fas fa-arrow-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
background: #ffffff;
|
||||
}
|
||||
.card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
|
||||
}
|
||||
.post-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.default-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 200px;
|
||||
background-color: #f8f9fa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.card-title {
|
||||
color: #2c3e50;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.input-group-text {
|
||||
border-right: 0;
|
||||
}
|
||||
.form-control:focus {
|
||||
box-shadow: none;
|
||||
border-color: #ced4da;
|
||||
}
|
||||
.form-select:focus {
|
||||
box-shadow: none;
|
||||
border-color: #ced4da;
|
||||
}
|
||||
.btn-outline-success:hover {
|
||||
transform: translateX(5px);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// El mismo script que antes...
|
||||
const posts = {
|
||||
frontmatter: JSON.stringify(Array.from(document.querySelectorAll('.post-item')).map(post => ({
|
||||
titulo: post.querySelector('.card-title').textContent.trim(),
|
||||
fecha: post.querySelector('.fa-calendar-alt').nextSibling.textContent.trim(),
|
||||
element: post.outerHTML
|
||||
})))
|
||||
};
|
||||
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const orderSelect = document.getElementById('orderSelect');
|
||||
const postsContainer = document.getElementById('postsContainer');
|
||||
|
||||
function updatePosts() {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const [orderBy, direction] = orderSelect.value.split('-');
|
||||
|
||||
let filteredPosts = JSON.parse(posts.frontmatter)
|
||||
.filter(post =>
|
||||
post.titulo.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
|
||||
// Ordenar posts
|
||||
filteredPosts.sort((a, b) => {
|
||||
if (orderBy === 'fecha') {
|
||||
const dateA = new Date(a.fecha);
|
||||
const dateB = new Date(b.fecha);
|
||||
return direction === 'asc' ? dateA - dateB : dateB - dateA;
|
||||
} else {
|
||||
const comparison = a.titulo.localeCompare(b.titulo);
|
||||
return direction === 'asc' ? comparison : -comparison;
|
||||
}
|
||||
});
|
||||
|
||||
// Actualizar DOM
|
||||
postsContainer.innerHTML = filteredPosts
|
||||
.map(post => post.element)
|
||||
.join('');
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', updatePosts);
|
||||
orderSelect.addEventListener('change', updatePosts);
|
||||
</script>
|
||||
Reference in New Issue
Block a user