Compare commits

...

5 Commits

Author SHA1 Message Date
caa5958b28 Nuevo proyecto: Podcast 2025-03-10 21:13:34 +01:00
c4f00f8725 Nueva sección de proyectos 2025-03-10 21:13:21 +01:00
1e6e23d62a Optimización de importaciones de Bootstrap 2025-03-10 21:12:49 +01:00
7e0d6d5a50 Optimización del código 2025-03-10 21:12:02 +01:00
4e8d2a379c Formulario de contacto 2025-03-10 21:11:21 +01:00
12 changed files with 491 additions and 429 deletions

BIN
public/imgs/logoPodcast.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

View File

@@ -1,4 +1,3 @@
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
@@ -9,18 +8,20 @@
</p>
</div>
<div class="col-md-6 text-center text-md-end">
<a href="#" class="text-white me-2"
><i class="fab fa-facebook-f"></i></a
>
<a href="#" class="text-white me-2"
><i class="fab fa-twitter"></i></a
>
<a href="#" class="text-white me-2"
><i class="fab fa-instagram"></i></a
>
<a href="#" class="text-white"
><i class="fab fa-linkedin-in"></i></a
>
<a href="#" class="text-white me-2 text-decoration-none">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="text-white me-2 text-decoration-none">
<i class="fab fa-twitter"></i>
</a>
<a href="#" class="text-white me-2 text-decoration-none">
<i class="fab fa-instagram"></i>
</a>
<a href="#" class="text-white me-2 text-decoration-none">
<i class="fab fa-linkedin-in"></i>
</a>
|
<a href="/contacto" class="text-light ms-2 text-decoration-none">Contacto</a>
</div>
</div>
</div>

View File

@@ -3,6 +3,13 @@ import { Image } from "astro:assets";
const { home, posts, proyectos } = Astro.props;
---
<head>
<meta charset="utf-8" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</head>
<main>
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href={home ? home : "/"}>
@@ -32,7 +39,7 @@ const { home, posts, proyectos } = Astro.props;
<a type="button" class="nav-link btn btn-light" href={posts ? posts : "/posts"}>Posts</a>
</li>
<li class="nav-item">
<a type="button" class="nav-link btn btn-light disabled" href={proyectos ? proyectos : "#proyectos"}
<a type="button" class="nav-link btn btn-light" href={proyectos ? proyectos : "/proyectos"}
>Proyectos</a
>
</li>
@@ -41,6 +48,8 @@ const { home, posts, proyectos } = Astro.props;
</div>
</nav>
</main>
<style>
.biglogo {
scale: 1.5;

View File

@@ -1,261 +0,0 @@
---
import RelatedPosts from "../components/PostsRelacionados.astro"; // Componente para posts relacionados
import Navbar from "../components/Navbar.astro";
import Footer from "../components/Footer.astro";
const { frontmatter } = Astro.props;
const headings = Astro.props.headings;
const description = frontmatter.descripcion;
// URLs para compartir en redes sociales
const shareUrl = new URL(Astro.url.pathname, Astro.site).toString();
const facebookShareUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(shareUrl)}`;
const twitterShareUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(shareUrl)}&text=${encodeURIComponent(frontmatter.titulo)}`;
const linkedinShareUrl = `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(shareUrl)}&title=${encodeURIComponent(frontmatter.titulo)}`;
const blogJsonLd = {
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": frontmatter.titulo,
"image": frontmatter.imagen && new URL(frontmatter.imagen, Astro.site),
"datePublished": frontmatter.fecha,
"dateModified": frontmatter.fecha,
"author": {
"@type": "Person",
"name": frontmatter.autor
},
"publisher": {
"@type": "Organization",
"name": "Ecobjetivos",
"logo": {
"@type": "ImageObject",
"url": new URL('/logo.png', Astro.site)
}
},
"description": description
};
---
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{frontmatter.titulo} - Ecobjetivos</title>
<link rel="icon" type="image/png" href="logo.png" />
<meta name="description" content={description} />
<link rel="canonical" href={new URL(Astro.url.pathname, Astro.site).toString()} />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="article" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={frontmatter.titulo} />
<meta property="og:description" content={description} />
<meta property="og:image" content={frontmatter.imagen && new URL(frontmatter.imagen, Astro.site)} />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={Astro.url} />
<meta property="twitter:title" content={frontmatter.titulo} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={frontmatter.imagen && new URL(frontmatter.imagen, Astro.site)} />
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-1JT18RF3R4"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-1JT18RF3R4");
</script>
<!-- Structured Data for Google -->
<script type="application/ld+json" set:html={JSON.stringify(blogJsonLd)} />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet" />
<style>
body {
font-family: "Arial", sans-serif;
line-height: 1.6;
color: #333;
}
.post-header {
background-color: #4caf50;
color: white;
padding: 2rem 0;
}
.post-content {
font-size: 1.1rem;
}
.post-content img {
max-width: 100%;
height: auto;
margin: 1.5rem 0;
}
.post-meta {
font-size: 0.9rem;
margin: 0px !important;
}
blockquote {
background-color: #f9f9f9;
border-left: 5px solid #4caf50;
padding: 1rem;
margin: 1rem 0;
font-style: italic;
}
.table-of-contents {
background-color: #f8f9fa;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
border: 1px solid #e9ecef;
}
.table-of-contents h4 {
color: #2c3e50;
border-bottom: 2px solid #4caf50;
font-size: 1.2rem;
}
.table-of-contents ul {
list-style-type: none;
padding-left: 0;
}
.table-of-contents a {
color: #495057;
text-decoration: none;
display: block;
border-radius: 5px;
transition: all 0.2s ease;
font-size: 0.9rem;
position: relative;
}
.table-of-contents a:hover {
color: #4caf50;
background-color: #e8f5e9;
padding-left: 0.6rem;
}
/* Estilos para la indentación visual */
.toc-level-2 { padding-left: 1.1rem; }
.toc-level-3 { padding-left: 2.1rem; }
.toc-level-4 { padding-left: 3.1rem; }
.toc-level-5 { padding-left: 4.1rem; }
.toc-level-6 { padding-left: 5.1rem; }
/* Líneas verticales para la indentación */
.toc-level-2,
.toc-level-3,
.toc-level-4,
.toc-level-5,
.toc-level-6 {
border-left: 2px solid #e9ecef;
margin-left: 0.5rem;
}
html { scroll-padding-top: 70px; }
img { max-width: 100%; height: auto; }
</style>
</head>
<body>
<Navbar proyectos="/" />
<header class="post-header">
<div class="container">
<h1 class="display-4">{frontmatter.titulo}</h1>
</div>
</header>
<main class="container my-5">
<div class="row">
<div class="col-lg-8">
<article class="post-content" data-bs-spy="scroll" data-bs-target="#toc" data-bs-offset="70" tabindex="0">
<slot />
</article>
</div>
<div class="col-lg-4">
<aside class="sticky-top" style="top: 5rem;">
<div class="d-none d-lg-block">
<!-- Se añade el id "toc" para ser usado por scrollspy -->
<div id="toc" class="table-of-contents p-3 mb-4">
<h4 class="mb-3 pb-2 fw-bold">Contenido</h4>
<ul class="m-0">
{headings.map((heading) => (
<li class={`mb-2 toc-level-${heading.depth}`}>
<a href={`#${heading.slug}`} class="py-1 px-2">
{heading.text}
</a>
</li>
))}
</ul>
</div>
</div>
<div class="card mb-4">
<div class="card-body">
<p class="post-meta">
<i class="fas fa-calendar-alt"></i>
{new Date(frontmatter.fecha).toLocaleDateString("es-ES", {
year: "numeric",
month: "long",
day: "numeric",
})}
&nbsp;|&nbsp;
<i class="fas fa-user"></i>
{frontmatter.autor}
</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Compartir</h5>
<a
href={facebookShareUrl}
target="_blank"
rel="noopener noreferrer"
class="btn btn-primary me-2"
>
<i class="fab fa-facebook-f fa-fw"></i>
</a>
<a
href={twitterShareUrl}
target="_blank"
rel="noopener noreferrer"
class="btn btn-info me-2"
>
<i class="fab fa-twitter fa-fw"></i>
</a>
<a
href={linkedinShareUrl}
target="_blank"
rel="noopener noreferrer"
class="btn btn-secondary"
>
<i class="fab fa-linkedin-in fa-fw"></i>
</a>
</div>
</div>
</aside>
</div>
</div>
<RelatedPosts currentPost={frontmatter} />
</main>
<Footer />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>
<style is:global>
@import url("https://fonts.googleapis.com/css2?family=Inter+Tight:ital@0;1&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Londrina+Sketch&display=swap");
h1, h2, h3, h4, h5, h6, p, a {
font-family: "Inter Tight", sans-serif !important;
font-optical-sizing: auto;
font-weight: 400 !important;
font-style: normal;
}
.londrina-sketch-regular {
font-family: "Londrina Sketch", sans-serif !important;
font-weight: 400;
font-style: normal;
}
</style>

125
src/pages/contacto.astro Normal file
View File

@@ -0,0 +1,125 @@
---
import Footer from "../components/Footer.astro";
import Navbar from "../components/Navbar.astro";
const animateOnScroll = `
document.addEventListener('DOMContentLoaded', () => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate__animated', 'animate__fadeIn');
entry.target.style.visibility = 'visible';
}
});
});
document.querySelectorAll('.animate-on-scroll').forEach(el => {
observer.observe(el);
});
});
`;
---
<html lang="es">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="generator" content={Astro.generator} />
<link rel="sitemap" href="/sitemap-index.xml" />
<meta
name="description"
content="Contacta con nosotros para cualquier duda sobre sostenibilidad y los Objetivos de Desarrollo Sostenible (ODS)."
/>
<link rel="icon" type="image/png" href="logo.png" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<title>Contacto | Ecobjetivos</title>
</head>
<body>
<div class="page-container">
<Navbar />
<main class="container py-5">
<h1 class="text-center mt-4 mb-5 animate__animated animate__fadeInDown">Contacta con Nosotros</h1>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow-lg animate-on-scroll">
<div class="card-body p-5">
<div class="row mb-4 justify-content-center">
<div class="col-md-6 mb-4 mb-md-0">
<div class="text-center">
<i class="fas fa-envelope fa-3x text-primary mb-3"></i>
<h3>Email</h3>
<p>Escríbenos a:</p>
<a href="mailto:ecobjetivos@h4ckdata.es" class="btn btn-primary">
ecobjetivos@h4ckdata.es
</a>
</div>
</div>
<!-- <div class="col-md-6">
<div class="text-center">
<i class="fab fa-discord fa-3x text-primary mb-3"></i>
<h3>Discord</h3>
<p>Únete a nuestra comunidad:</p>
<a href="https://discord.gg/tuenlace" class="btn btn-primary">
Servidor de Discord
</a>
</div>
</div> -->
</div>
<!--
<hr class="my-5" />
<form class="animate-on-scroll">
<h3 class="text-center mb-4">O envíanos un mensaje directamente</h3>
<div class="mb-3">
<label for="nombre" class="form-label">Nombre</label>
<input type="text" class="form-control" id="nombre" required />
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" required />
</div>
<div class="mb-3">
<label for="asunto" class="form-label">Asunto</label>
<input type="text" class="form-control" id="asunto" required />
</div>
<div class="mb-3">
<label for="mensaje" class="form-label">Mensaje</label>
<textarea class="form-control" id="mensaje" rows="5" required></textarea>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary btn-lg">Enviar Mensaje</button>
</div>
</form> -->
</div>
</div>
</div>
</div>
</main>
<Footer/>
</div>
<script set:html={animateOnScroll} />
</body>
</html>
<style>
.page-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
</style>

View File

@@ -4,6 +4,7 @@ import Footer from "../components/Footer.astro";
import ListadoPostsHorizontal from "../components/ListadoPostsHorizontal.astro";
import Navbar from "../components/Navbar.astro";
import { Image } from "astro:assets";
import { proyectos } from "../pages/proyectos/index.astro";
const animateOnScroll = `
document.addEventListener('DOMContentLoaded', () => {
@@ -51,12 +52,6 @@ const animateOnScroll = `
content="Tu fuente de información sobre sostenibilidad y los Objetivos de Desarrollo Sostenible (ODS). Descubre cómo contribuir a un futuro más sostenible."
/>
<link rel="icon" type="image/png" href="logo.png" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
rel="stylesheet"
@@ -71,7 +66,7 @@ const animateOnScroll = `
<Navbar />
<header class="header-bg text-white">
<img
src={"/imgs/bosqueverde.png"}
src="/imgs/bosqueverde.png"
alt="Bosque Verde"
class="video-bg"
/>
@@ -227,46 +222,17 @@ const animateOnScroll = `
<h2 class="text-center mb-5 animate-on-scroll pt-2">
Nuestros Proyectos Destacados
</h2>
<div class="row">
<div class="row justify-content-center">
{
[
{
title: "Reforestación Urbana",
description:
"Hemos plantado más de 200 árboles en zonas urbanas para mejorar la calidad del aire y crear espacios verdes.",
image: "/imgs/reforestacion.jpg",
link: "/proyectos/reforestacion",
},
{
title: "Talleres ODS en Escuelas",
description:
"Programa educativo que ha llegado a 15 escuelas enseñando los ODS a más de 500 estudiantes.",
image: "/imgs/talleres-escuelas.jpg",
link: "/proyectos/talleres-ods",
},
{
title: "Podcast EcoVoces",
description:
"Serie de episodios que explora los 17 ODS con expertos en sostenibilidad y activistas locales.",
image: "/imgs/podcast-ods.jpg",
link: "/podcast",
},
{
title: "Campaña Agua Limpia",
description:
"Iniciativa para instalar sistemas de filtración en comunidades con acceso limitado a agua potable.",
image: "/imgs/agua-limpia.jpg",
link: "/proyectos/agua-limpia",
},
].map((project, index) => (
proyectos.map((project) => (
<div class="col-md-6 mb-4 animate-on-scroll">
<div class="card h-100">
<div class="row g-0">
<div class="col-md-4">
<img
src={project.image}
class="img-fluid rounded-start h-100 object-fit-cover"
alt={project.title}
src={project.imagen}
class="img-fluid rounded-start"
alt={project.titulo}
/>
</div>
<div class="col-md-8">
@@ -275,13 +241,13 @@ const animateOnScroll = `
class="card-title"
aria-label="Proyecto"
>
{project.title}
{project.titulo}
</h5>
<p class="card-text flex-grow-1">
{project.description}
<p class="card-text flex-grow-1 line-clamp">
{project.descripcion}
</p>
<a
href={project.link}
href={project.url}
class="btn btn-success mt-auto"
>
Ver detalles
@@ -317,9 +283,6 @@ const animateOnScroll = `
<Footer />
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
></script>
<script set:html={animateOnScroll} />
</body>
</html>
@@ -401,4 +364,11 @@ const animateOnScroll = `
transform: translateY(-5px);
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
}
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>

View File

@@ -37,10 +37,6 @@ const urlSitio = Astro.site; // Reemplaza con la URL de tu sitio
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Participa Ahora | Ecobjetivos</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
rel="stylesheet"
@@ -217,5 +213,3 @@ const urlSitio = Astro.site; // Reemplaza con la URL de tu sitio
</script>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

View File

@@ -170,7 +170,7 @@ const blogJsonLd = {
</style>
</head>
<body>
<Navbar proyectos="/" />
<Navbar />
<header class="post-header">
<div class="container">

View File

@@ -1,6 +1,6 @@
---
import Navbar from "../components/Navbar.astro";
import ListadoPosts from "../layouts/ListadoPosts.astro";
import Navbar from "../../components/Navbar.astro";
import ListadoPosts from "../../layouts/ListadoPosts.astro";
---
<html lang="es">
@@ -9,12 +9,6 @@ import ListadoPosts from "../layouts/ListadoPosts.astro";
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content={Astro.generator} />
<link rel="icon" type="image/png" href="logo.png" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
rel="stylesheet"
@@ -40,9 +34,5 @@ import ListadoPosts from "../layouts/ListadoPosts.astro";
<Navbar />
<ListadoPosts />
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"></script>
</body>
</html>

View 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>

View File

@@ -35,10 +35,34 @@ const episodes = [
title: "Criterios ASG",
description:
"🎙️ Bienvenidos a Arreglamos el Mundo, el podcast donde exploramos ideas, soluciones y reflexiones para construir un futuro más sostenible y justo. 🌎 En este episodio, nos sumergimos en los criterios ASG: ambiental, social y de gobernanza. ¿Qué significan? ¿Cómo están transformando el mundo de los negocios, las inversiones y nuestras vidas? Acompáñanos mientras desglosamos cómo estas herramientas nos acercan a un mundo mejor. ¡Comencemos a arreglar el mundo, un criterio a la vez! 🌱✨",
spotifyLink: "https://open.spotify.com/episode/6dqCt8UAukJ8xD0lJnLZgp?si=2BDei-9IQqSVNyvXAYZj_Q",
spotifyLink: "https://open.spotify.com/episode/218xJHgfhDBPAtr1qELCMa?si=FpuHWjR4TEegn0dDJLnO1w",
duration: "14:11",
date: "10 de diciembre de 2024",
},
{
title: "Retos Ambientales",
description:
"🎙️ Bienvenidos a Arreglamos el Mundo, el espacio donde debatimos, reflexionamos y soñamos con un planeta más habitable para todos. 🌎 En este episodio, ponemos sobre la mesa los retos ambientales que enfrentamos hoy: desde el cambio climático hasta la pérdida de biodiversidad y la gestión sostenible de nuestros recursos. ¿Qué desafíos debemos superar y qué podemos hacer para marcar la diferencia? Es hora de analizar el panorama, cuestionar nuestras acciones y buscar soluciones que realmente arreglen el mundo. 🌱💡",
spotifyLink: "https://open.spotify.com/episode/4g6wy4VLz9RPWu4Iu01cdX?si=NaVoDOoJTBKu54fkKQiOJQ",
duration: "10:03",
date: "10 de diciembre de 2024",
},
{
title: "Cómo Minimizar los Impactos Ambientales??",
description:
"🎙️ Bienvenidos a Arreglamos el Mundo, el podcast donde exploramos ideas para hacer del planeta un lugar mejor. 🌍✨ En este episodio, hablamos sobre cómo minimizar los impactos ambientales. Desde pequeñas acciones en nuestro día a día hasta grandes estrategias a nivel global, analizaremos qué podemos hacer para reducir nuestra huella ecológica y proteger los recursos naturales. ¡Acompáñanos mientras descubrimos juntos cómo marcar la diferencia y avanzar hacia un futuro más sostenible! 🌱💡",
spotifyLink: "https://open.spotify.com/episode/2tWQ9PFQfo1qK55rop8h0s?si=9KTe45o9Rw-KBtIqsAlU4g",
duration: "9:02",
date: "10 de diciembre de 2024",
},
{
title: '¡¡Hemos vuelto!! Hablemos de: "Los 17 Puntos"',
description:
"En Agenda 2030: 17 Pasos hacia un Mundo Mejor, exploramos cada uno de los 17 Objetivos de Desarrollo Sostenible (ODS) propuestos por la ONU. Acompáñanos en este viaje donde analizamos los retos globales, las soluciones innovadoras y el impacto de estas metas en nuestra sociedad, economía y medioambiente. Con entrevistas a expertos, historias inspiradoras y casos reales, descubrirás cómo tú también puedes contribuir a un futuro más justo, sostenible e inclusivo. ¡Sintoniza y forma parte del cambio!",
spotifyLink: "https://open.spotify.com/episode/6BluxrOOSnji7wkUt50nk3?si=VQf7Na7jQ4C7AnA4aY2leQ",
duration: "22:08",
date: "3 de marzo de 2025",
},
{
title: "Economía Verde y Circular",
description:
@@ -102,7 +126,7 @@ const episodes = [
<h1
class="display-3 mb-4 animate__animated animate__fadeInDown"
>
Arreglamos el Mundo?
¿Arreglamos el Mundo?
</h1>
<p
class="lead mb-4 animate__animated animate__fadeInUp animate__delay-1s"
@@ -137,7 +161,7 @@ const episodes = [
<div class="col-lg-6 animate-on-scroll">
<h2 class="display-5 mb-4">Sobre el Podcast</h2>
<p class="lead">
<strong>Arreglamos el Mundo</strong> es un Podcast dinámico y entretenido
<strong>¿Arreglamos el Mundo?</strong> es un Podcast dinámico y entretenido
que aborda los desafíos y soluciones relacionadas
con la Sostenibilidad.
</p>
@@ -217,47 +241,15 @@ const episodes = [
<section class="py-5">
<div class="container">
<div class="row">
<div
class="col-lg-8 mx-auto text-center animate-on-scroll"
>
<div class="col-lg-8 mx-auto text-center animate-on-scroll">
<h2 class="mb-4">¿Por qué escuchar Arreglamos el Mundo?</h2>
<div class="row g-4 mt-3">
<div class="col-md-4">
<div class="col-md-12">
<div class="p-3 bg-light rounded-3 h-100">
<i
class="fas fa-graduation-cap text-success fa-2x mb-3"
></i>
<h3 class="h5">Educación</h3>
<p class="mb-0">
Aprende sobre los ODS de forma clara
y amena con expertos en cada tema.
</p>
</div>
</div>
<div class="col-md-4">
<div class="p-3 bg-light rounded-3 h-100">
<i
class="fas fa-lightbulb text-success fa-2x mb-3"
></i>
<h3 class="h5">Inspiración</h3>
<p class="mb-0">
Descubre historias de proyectos
exitosos que están generando cambios
reales.
</p>
</div>
</div>
<div class="col-md-4">
<div class="p-3 bg-light rounded-3 h-100">
<i
class="fas fa-hands-helping text-success fa-2x mb-3"
></i>
<h3 class="h5">Acción</h3>
<p class="mb-0">
Cada episodio incluye consejos
prácticos que puedes implementar en
tu día a día.
</p>
<video controls class="w-100">
<source src="/imgs/videoPodcast.mp4" type="video/mp4">
Tu navegador no soporta la reproducción de videos.
</video>
</div>
</div>
</div>
@@ -332,7 +324,7 @@ const episodes = [
left: 0;
width: 100%;
height: 100%;
background-image: url("/imgs/podcast-pattern.png");
/*background-image: url("/imgs/podcast-pattern.png");*/
opacity: 0.1;
}