diff options
Diffstat (limited to 'src/pages')
| -rw-r--r-- | src/pages/blog/[id].astro | 10 | ||||
| -rw-r--r-- | src/pages/blog/index.astro | 317 | ||||
| -rw-r--r-- | src/pages/portfolio/[id].astro | 57 | ||||
| -rw-r--r-- | src/pages/portfolio/index.astro | 2 |
4 files changed, 15 insertions, 371 deletions
diff --git a/src/pages/blog/[id].astro b/src/pages/blog/[id].astro index 935a796..3dc324a 100644 --- a/src/pages/blog/[id].astro +++ b/src/pages/blog/[id].astro @@ -1,5 +1,5 @@ --- -import Layout from "../../layouts/Layout.astro"; +import Layout from "@/layouts/Layout.astro"; import { getCollection, render } from "astro:content"; import { type GetStaticPaths } from "astro"; @@ -32,6 +32,7 @@ const schema = { "@type": "BlogPosting", headline: entry.data.title, datePublished: entry.data.publishedAt.toISOString(), + keywords: entry.data.tags || [], author: { "@type": "Person", name: "Ariel Costas Guerrero", @@ -39,7 +40,8 @@ const schema = { publisher: { "@type": "Person", name: "Ariel Costas Guerrero", - logo: { + url: "https://www.costas.dev", + image: { "@type": "ImageObject", url: "https://www.costas.dev/favicon.png", }, @@ -74,6 +76,10 @@ const schema = { </small> <Content /> + + <p> + <a href="/blog">Volver al blog</a> + </p> </Layout> <style lang="scss"> diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index b74781b..10a464b 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -1,318 +1,5 @@ --- -import { getCollection } from "astro:content"; -import Layout from "../../layouts/Layout.astro"; - -const blogCollection = (await getCollection("blog")).sort((a, b) => { - return b.data.publishedAt.getTime() - a.data.publishedAt.getTime(); -}); - -// Agrupar artículos por fecha -const groupedPosts = blogCollection.reduce( - (acc: Record<string, any[]>, post) => { - const year = post.data.publishedAt.getFullYear(); - const month = post.data.publishedAt.getMonth() + 1; - const key = `${year}-${month}`; - if (!acc[key]) { - acc[key] = []; - } - acc[key].push(post); - return acc; - }, - {}, -); - -// Colección de todas las etiquetas únicas -const allTags = [...new Set(blogCollection.flatMap(post => post.data.tags || []))].sort(); - -function humaniseDate(date: Date) { - const result = date.toLocaleDateString("es-ES", { - month: "long", - year: "numeric", - }); - return result.charAt(0).toUpperCase() + result.slice(1); -} - -const schema = { - "@context": "https://schema.org", - "@type": "Blog", - headline: "Blog de Ariel Costas", - description: - "En este blog encontrarás artículos sobre desarrollo, tecnología y otras temáticas que pueda querer compartir. Disclaimer de siempre: las opiniones son mías, y no representan a ninguna empresa o institución.", - publisher: { - "@type": "Person", - name: "Ariel Costas", - }, - author: { - "@type": "Person", - name: "Ariel Costas", - }, -}; +import BlogListLayout from "@/layouts/BlogListLayout.astro"; --- -<Layout - title="Blog" - description="Artículos sobre desarrollo, tecnología y otras temáticas que pueda querer compartir. Disclaimer de siempre: las opiniones son mías, y no representan a ninguna empresa o institución." -> - <script - is:inline - type="application/ld+json" - slot="head-jsonld" - set:html={JSON.stringify(schema)} - /> - - <h1>Blog de Ariel Costas</h1> - - <p> - En este blog encontrarás artículos sobre desarrollo, tecnología y otras - temáticas que pueda querer compartir. Disclaimer de siempre: las opiniones - son mías, y no representan a ninguna empresa o institución. - </p> - - {allTags.length > 0 && ( - <div class="tags-container"> - <h2>Etiquetas</h2> - <div class="tag-filter"> - <button class="tag-button active" data-tag="all">Todas</button> - {allTags.map((tag) => ( - <button class="tag-button" data-tag={tag}>{tag}</button> - ))} - </div> - </div> - )} - - <div id="blog-posts"> - { - Object.entries(groupedPosts).map(([key, posts]) => ( - <section class="post-section" data-date={key}> - <h2>{humaniseDate(new Date(key))}</h2> - <ul> - {posts.map((post) => { - const postTags = post.data.tags || []; - const tagsAttribute = postTags.join(','); - return ( - <li class="post-item" data-tags={tagsAttribute}> - <a href={`/blog/${post.id}`}>{post.data.title}</a> - {postTags.length > 0 && ( - <ul class="post-tags"> - {postTags.map((tag: string) => ( - <li> - <button class="tag-link" data-tag={tag}> - {tag} - </button> - </li> - ))} - </ul> - )} - </li> - ); - })} - </ul> - </section> - )) - } - </div> - - <script> - // Script para el filtrado de artículos por etiqueta - document.addEventListener('DOMContentLoaded', () => { - const tagButtons = document.querySelectorAll('.tag-button'); - const tagLinks = document.querySelectorAll('.tag-link'); - const postItems = document.querySelectorAll('.post-item'); - const postSections = document.querySelectorAll('.post-section'); - - // Función para filtrar los artículos por etiqueta - function filterByTag(tag: string) { - // Primero, restablecer la visibilidad de todos los elementos - postItems.forEach(item => { - (item as HTMLElement).style.display = ''; - }); - postSections.forEach(section => { - (section as HTMLElement).style.display = ''; - }); - - // Si no es 'todas', filtrar por etiqueta - if (tag !== 'all') { - postItems.forEach(item => { - const itemEl = item as HTMLElement; - const tagsAttr = itemEl.dataset.tags || ''; - const itemTags = tagsAttr ? tagsAttr.split(',') : []; - if (!itemTags.includes(tag)) { - itemEl.style.display = 'none'; - } - }); - - // Ocultar secciones que no tienen artículos visibles - postSections.forEach(section => { - const items = section.querySelectorAll('.post-item'); - let allHidden = true; - - items.forEach(item => { - if ((item as HTMLElement).style.display !== 'none') { - allHidden = false; - } - }); - - if (allHidden) { - (section as HTMLElement).style.display = 'none'; - } - }); - } - - // Actualizar estado activo de los botones - tagButtons.forEach(button => { - if ((button as HTMLElement).dataset.tag === tag) { - button.classList.add('active'); - } else { - button.classList.remove('active'); - } - }); - - // Actualizar URL con el parámetro de consulta - if (tag === 'all') { - history.replaceState(null, document.title, window.location.pathname); - } else { - history.replaceState(null, document.title, `?tag=${encodeURIComponent(tag)}`); - } - - // Añadir un log para depuración - console.log(`Filtrado por etiqueta: ${tag}`); - console.log(`Artículos visibles: ${document.querySelectorAll('.post-item:not([style*="display: none"])')?.length || 0}`); - } - - // Eventos de clic para los botones de etiquetas - tagButtons.forEach(button => { - button.addEventListener('click', () => { - const tag = (button as HTMLElement).dataset.tag; - if (tag) filterByTag(tag); - }); - }); - - // Eventos de clic para los enlaces de etiquetas dentro de los posts - tagLinks.forEach(link => { - link.addEventListener('click', (e) => { - e.preventDefault(); - const tag = (link as HTMLElement).dataset.tag; - if (tag) filterByTag(tag); - - // Desplazamiento suave hacia arriba para ver todos los resultados - const tagsContainer = document.querySelector('.tags-container'); - if (tagsContainer) { - window.scrollTo({ - top: (tagsContainer as HTMLElement).offsetTop - 20, - behavior: 'smooth' - }); - } - }); - }); - - // Verificar si hay un parámetro de consulta para filtrar - const urlParams = new URLSearchParams(window.location.search); - const tagParam = urlParams.get('tag'); - - if (tagParam) { - const tagExists = Array.from(tagButtons).some(button => - (button as HTMLElement).dataset.tag === tagParam - ); - if (tagExists) { - filterByTag(tagParam); - } - } - }); - </script> -</Layout> - -<style lang="scss"> - @use "../../../styles/variables" as v; - @use "sass:color"; - - .tags-container { - margin-bottom: 2rem; - } - - .tag-filter { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin-bottom: 1.5rem; - } - - .tag-button { - padding: 0.25rem 0.6rem; - background-color: v.$light; - color: v.$accent; - border: 1px solid v.$accent; - border-radius: 1.5rem; - font-size: 0.85rem; - font-family: v.$monoFontStack; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: v.$shadow; - - &:hover { - background-color: color.adjust(v.$accent, $lightness: 45%); - color: v.$accentDark; - transform: translateY(-1px); - } - - &.active { - background-color: v.$accent; - color: v.$lightAlt; - border-color: v.$accentDark; - } - } - - .post-tags { - display: inline-flex; - list-style: none; - margin: 0; - padding: 0; - gap: 0.25rem; - margin-left: 0.5rem; - } - - .post-tags li { - display: inline; - } - - .tag-link { - display: inline-block; - padding: 0.1rem 0.4rem; - background-color: color.adjust(v.$background, $lightness: -3%); - color: v.$accentDark; - border: none; - border-radius: 1rem; - font-size: 0.75rem; - font-family: v.$monoFontStack; - text-decoration: none; - cursor: pointer; - transition: all 0.2s ease; - - &:hover { - background-color: color.adjust(v.$accent, $lightness: 45%); - color: v.$accentDark; - transform: translateY(-1px); - } - } - - /* Efecto de transición para el filtrado */ - .post-item { - transition: all 0.3s ease; - } - - .post-section { - transition: opacity 0.3s ease; - } - - #blog-posts { - min-height: 200px; - } - - /* Mejora el aspecto de los enlaces de posts */ - .post-item { - margin-bottom: 0.5rem; - - a { - font-weight: 500; - } - } -</style> +<BlogListLayout /> diff --git a/src/pages/portfolio/[id].astro b/src/pages/portfolio/[id].astro index b92ecbd..601ff84 100644 --- a/src/pages/portfolio/[id].astro +++ b/src/pages/portfolio/[id].astro @@ -1,12 +1,7 @@ --- -import Layout from "../../layouts/Layout.astro"; -import { getCollection, render } from "astro:content"; -import { type GetStaticPaths } from "astro"; -import TechnologyBadge from "../../partials/TechnologyBadge.astro"; - -interface Props { - entry: any; -} +import type { GetStaticPaths } from "astro"; +import { getCollection } from "astro:content"; +import PortfolioItemLayout from "@/layouts/PortfolioItemLayout.astro"; export const getStaticPaths: GetStaticPaths = async () => { const entries = await getCollection("portfolio"); @@ -17,50 +12,6 @@ export const getStaticPaths: GetStaticPaths = async () => { }; const { entry } = Astro.props; -const { Content } = await render(entry); --- -<Layout title={entry.data.title} description={entry.data.description}> - <a id="link-back" href="/portfolio"> - <svg - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 24 24" - fill="none" - stroke="currentColor" - stroke-width="2" - stroke-linecap="round" - stroke-linejoin="round" - class="w-6 h-6 inline-block mr-2" - > - <polyline points="15 18 9 12 15 6"></polyline> - </svg> - Volver al portfolio - </a> - - <h1>{entry.data.title}</h1> - - <Content /> - - <h2>Tecnologías utilizadas</h2> - - { - entry.data.technologies.map((technology: string) => ( - <TechnologyBadge size="small" code={technology} /> - )) - } -</Layout> - -<style> - a#link-back { - display: inline-flex; - align-items: center; - gap: 0.5rem; - text-decoration: none; - text-transform: uppercase; - transition: color 0.2s ease-in-out; - } - - a#link-back svg { - height: 1em; - } -</style> +<PortfolioItemLayout entry={entry} /> diff --git a/src/pages/portfolio/index.astro b/src/pages/portfolio/index.astro index 17c4637..f5f1250 100644 --- a/src/pages/portfolio/index.astro +++ b/src/pages/portfolio/index.astro @@ -1,5 +1,5 @@ --- -import PortfolioPageLayout from "../../layouts/PortfolioPageLayout.astro"; +import PortfolioPageLayout from "@/layouts/PortfolioPageLayout.astro"; --- <PortfolioPageLayout /> |
