Nueva sección de proyectos
This commit is contained in:
BIN
public/imgs/logoPodcast.png
Normal file
BIN
public/imgs/logoPodcast.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 377 KiB |
@@ -170,7 +170,7 @@ const blogJsonLd = {
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Navbar proyectos="/" />
|
<Navbar />
|
||||||
|
|
||||||
<header class="post-header">
|
<header class="post-header">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
242
src/pages/proyectos/index.astro
Normal file
242
src/pages/proyectos/index.astro
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
---
|
||||||
|
import Navbar from "../../components/Navbar.astro";
|
||||||
|
|
||||||
|
export const proyectos = [
|
||||||
|
{
|
||||||
|
titulo: "Podcast ¿Arreglamos el Mundo?",
|
||||||
|
descripcion: "Un Podcast dinámico y entretenido que aborda los desafíos y soluciones relacionadas con la Sostenibilidad. Liderado por Rafa y Vicente, cada episodio se convierte en un espacio de debate y aprendizaje. Junto a ellos, los expertos invitados María Jesús y Rubén. Con conversaciones cercanas, datos relevantes y un toque de humor, este equipo busca, literalmente, arreglar el mundo. 🌍✨",
|
||||||
|
imagen: "/imgs/logoPodcast.png",
|
||||||
|
autor: "Rafa, Vicen, Rubén y María Jesús",
|
||||||
|
fecha: "2024-03-10",
|
||||||
|
url: "/proyectos/podcast"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const orderProyectos = (proyectos, orderBy = "fecha", ascending = false) => {
|
||||||
|
return proyectos.sort((a, b) => {
|
||||||
|
if (orderBy === "fecha") {
|
||||||
|
const comparison = new Date(b.fecha).getTime() - new Date(a.fecha).getTime();
|
||||||
|
return ascending ? -comparison : comparison;
|
||||||
|
} else if (orderBy === "titulo") {
|
||||||
|
const comparison = a.titulo.localeCompare(b.titulo);
|
||||||
|
return ascending ? comparison : -comparison;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialProyectos = orderProyectos(proyectos, "fecha", false);
|
||||||
|
---
|
||||||
|
<body>
|
||||||
|
<Navbar />
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="text-center mb-5 mt-3">
|
||||||
|
<h1 class="display-4">Proyectos Sostenibles</h1>
|
||||||
|
<p class="lead text-muted">
|
||||||
|
Descubre nuestras iniciativas para un futuro más sostenible
|
||||||
|
</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 proyectos..."
|
||||||
|
/>
|
||||||
|
</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 proyectos -->
|
||||||
|
<div class="row justify-content-center" id="proyectosContainer">
|
||||||
|
{initialProyectos.map((proyecto) => (
|
||||||
|
<div class="col-md-8 mb-4 proyecto-item">
|
||||||
|
<article class="card shadow-sm h-100 border-0">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-md-4">
|
||||||
|
{proyecto.imagen ? (
|
||||||
|
<img
|
||||||
|
src={proyecto.imagen}
|
||||||
|
class="proyecto-image rounded-start"
|
||||||
|
alt={proyecto.titulo}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div class="default-image rounded-start">
|
||||||
|
<i class="fas fa-leaf fa-3x text-success" />
|
||||||
|
</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">{proyecto.titulo}</h2>
|
||||||
|
<p class="card-text text-muted">
|
||||||
|
{proyecto.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" />
|
||||||
|
{proyecto.autor}
|
||||||
|
</small>
|
||||||
|
<small class="text-muted d-block">
|
||||||
|
<i class="far fa-calendar-alt me-2" />
|
||||||
|
<time datetime={proyecto.fecha}>
|
||||||
|
{new Date(proyecto.fecha).toLocaleDateString(
|
||||||
|
"es-ES",
|
||||||
|
{
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</time>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href={proyecto.url}
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
>
|
||||||
|
Ver proyecto
|
||||||
|
<i class="fas fa-arrow-right ms-2" />
|
||||||
|
</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 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
|
||||||
|
}
|
||||||
|
.proyecto-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>
|
||||||
|
interface Proyecto {
|
||||||
|
titulo: string;
|
||||||
|
fecha: string;
|
||||||
|
element: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proyectos = {
|
||||||
|
frontmatter: JSON.stringify(Array.from(document.querySelectorAll('.proyecto-item')).map(proyecto => {
|
||||||
|
const timeEl = proyecto.querySelector('time');
|
||||||
|
const titleEl = proyecto.querySelector('.card-title');
|
||||||
|
return {
|
||||||
|
titulo: titleEl?.textContent?.trim() || '',
|
||||||
|
fecha: timeEl?.getAttribute('datetime') || '',
|
||||||
|
element: proyecto.outerHTML
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchInput = document.getElementById('searchInput') as HTMLInputElement;
|
||||||
|
const orderSelect = document.getElementById('orderSelect') as HTMLSelectElement;
|
||||||
|
const proyectosContainer = document.getElementById('proyectosContainer');
|
||||||
|
const proyectosList = JSON.parse(proyectos.frontmatter) as Proyecto[];
|
||||||
|
|
||||||
|
function filterAndSortProyectos() {
|
||||||
|
if (!searchInput || !orderSelect || !proyectosContainer) return;
|
||||||
|
|
||||||
|
const searchTerm = searchInput.value.toLowerCase();
|
||||||
|
const [orderBy, direction] = orderSelect.value.split('-');
|
||||||
|
|
||||||
|
let filteredProyectos = proyectosList.filter(proyecto =>
|
||||||
|
proyecto.titulo.toLowerCase().includes(searchTerm)
|
||||||
|
);
|
||||||
|
|
||||||
|
filteredProyectos.sort((a, b) => {
|
||||||
|
if (orderBy === 'fecha') {
|
||||||
|
const dateA = new Date(a.fecha).getTime();
|
||||||
|
const dateB = new Date(b.fecha).getTime();
|
||||||
|
const comparison = dateB - dateA;
|
||||||
|
return direction === 'asc' ? -comparison : comparison;
|
||||||
|
} else if (orderBy === 'titulo') {
|
||||||
|
const comparison = a.titulo.localeCompare(b.titulo);
|
||||||
|
return direction === 'asc' ? comparison : -comparison;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
proyectosContainer.innerHTML = filteredProyectos
|
||||||
|
.map(proyecto => proyecto.element)
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
searchInput?.addEventListener('input', filterAndSortProyectos);
|
||||||
|
orderSelect?.addEventListener('change', filterAndSortProyectos);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
Reference in New Issue
Block a user