diff options
Diffstat (limited to 'src/layouts')
| -rw-r--r-- | src/layouts/HomePageLayout.astro | 46 | ||||
| -rw-r--r-- | src/layouts/Layout.astro | 15 | ||||
| -rw-r--r-- | src/layouts/PortfolioListLayout.astro | 137 | ||||
| -rw-r--r-- | src/layouts/PortfolioSingleLayout.astro | 370 |
4 files changed, 13 insertions, 555 deletions
diff --git a/src/layouts/HomePageLayout.astro b/src/layouts/HomePageLayout.astro index fb3cf34..ca009a5 100644 --- a/src/layouts/HomePageLayout.astro +++ b/src/layouts/HomePageLayout.astro @@ -24,56 +24,12 @@ const schema = { /> <h1>Inicio</h1> + <p> Te doy la bienvenida a mi web. Me llamo Ariel, y aquí encontrarás información sobre mí y mis proyectos. </p> - <h2>¿Quién soy?</h2> - - <p> - Soy un desarrollador de software con varios años de experiencia en el - sector, especializado en el desarrollo de aplicaciones web y la - administración de sistemas Cloud. Me apasiona la tecnología y disfruto - creando soluciones prácticas y eficientes para resolver problemas reales, - simplificando la vida y el trabajo de las personas. - </p> - - <p> - En mi tiempo libre, fuera de mi trabajo, me interesan temas como la - filosofía, la economía y las finanzas, así como el derecho y la política. Me - gusta aprender sobre cómo funcionan las cosas y cómo se relacionan entre sí, - y reflexionar sobre el impacto que tienen en nuestra sociedad y en nuestras - vidas cotidianas. - </p> - - <h2>¿Qué hago?</h2> - - <p> - Actualmente trabajo como desarrollador de software y administrador Cloud en - Estelaria Solutions, una empresa de tecnología en Vigo (España). Me encargo - de desarrollar aplicaciones web en PHP y desplegarlas en la nube de forma - segura y eficiente. - </p> - - <a href="/trajectory/">Conoce más sobre mi trayectoria profesional</a> - - <p> - También realizo ocasinalmente proyectos personales y freelance para clientes - que necesitan soluciones a medida o apoyo técnico en sus proyectos. Me gusta - trabajar con tecnologías modernas y aprender nuevas habilidades para mejorar - mi trabajo y ofrecer un mejor servicio a mis clientes. - </p> - - <p> - Si necesitas ayuda con un proyecto o quieres colaborar conmigo, no dudes en - ponerte en contacto conmigo a través de mi correo electrónico o mis redes - sociales. - </p> - - <a href="/portfolio/">Echa un vistazo a mi portfolio</a> - - <h2>Mis reflexiones</h2> <p> En mi blog comparto mis reflexiones, aprendizajes y experiencias sobre los temas que me interesan, además de hablar ocasionalmente sobre tecnología y diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 6e389e2..3aa2dd0 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,6 +1,4 @@ --- -import "@fontsource-variable/roboto"; -import "@fontsource-variable/roboto-mono"; import Header from "../partials/Header.astro"; import Footer from "../partials/Footer.astro"; @@ -137,8 +135,19 @@ const { title, description, empty } = Astro.props; background-color: color.adjust($accent, $alpha: -0.85); } + ul:has(li) { + padding-left: 1.25rem; + margin-top: 0; + margin-bottom: 1.5rem; + + display: flex; + flex-direction: column; + gap: 0.5rem; + } + li > time { - font-family: $monoFontStack; + font-size: 0.95rem; + user-select: none; } main { diff --git a/src/layouts/PortfolioListLayout.astro b/src/layouts/PortfolioListLayout.astro deleted file mode 100644 index b509bec..0000000 --- a/src/layouts/PortfolioListLayout.astro +++ /dev/null @@ -1,137 +0,0 @@ ---- -import t from "../i18n/es.json"; - -import Layout from "./Layout.astro"; -import PortfolioProject from "@/components/PortfolioProject.astro"; - -const schema = { - "@context": "https://schema.org", - "@type": "WebPage", - url: "https://www.costas.dev/portfolio", - headline: t.portfolioPage.headline, -}; ---- - -<Layout title={t.portfolioPage.title} description={t.portfolioPage.description}> - <script - is:inline - type="application/ld+json" - slot="head-jsonld" - set:html={JSON.stringify(schema)} - /> - - <h1>{t.portfolioPage.headline}</h1> - - <p set:html={t.portfolioPage.intro} /> - - <h2>{t.portfolioPage.freelanceTitle}</h2> - - <p>{t.portfolioPage.freelanceDesc}</p> - - <section> - <PortfolioProject - title="Mapa patrimonial de la Costa Ártabra" - summary="Desarrollo de una aplicación completa para el patrimonio cultural y militar de la Costa Ártabra, con un sistema CMS para el personal de la administración y una aplicación web progresiva (PWA) para visualizar el mapa y planificar rutas." - tags={["dotnet", "react", "mysql", "ubuntu"]} - detailsLink="/portfolio/mapa-ferrol/" - onlineLink="https://mapacostaartabramilitar.com" - /> - - <PortfolioProject - title="Extractor de pedidos venta online" - summary="Aplicación de escritorio que extrae los datos sobre los pedidos on-line de diversas plataformas (como WooCommerce, Amazon y Ebay)." - tags={["java", "windows"]} - detailsLink="/portfolio/order-extractor/" - /> - - <PortfolioProject - title="Museo a ceo aberto de Ponteareas" - summary="Desarrollo de visualización de contenido turístico para el Concello de Ponteareas. Incluye contenido en 360º e incrustación de vídeos de YouTube. Realizado en 2021." - tags={["php", "web"]} - detailsLink="/portfolio/qr-ponteareas/" - /> - - <PortfolioProject - title="QR Touro turístico" - summary="Desarrollo de un generador estático en TypeScript para información turística del Concello de Touro. Realizado en 2020." - tags={["typescript", "web"]} - detailsLink="/portfolio/qr-touro/" - /> - - <PortfolioProject - title="Consultoría WordPress" - summary="Trabajos de mantenimiento, optimización y migración de sitios web WordPress y tiendas online WooCommerce." - tags={["php", "wordpress"]} - detailsLink="/portfolio/wp-consulting/" - /> - </section> - - <h2>{t.portfolioPage.ownProjectsTitle}</h2> - - <p>{t.portfolioPage.ownProjectsDesc}</p> - - <section> - <PortfolioProject - title="Web personal" - summary="Desarrollado con Astro, un generador de sitios web estáticos que permite escribir contenido en Markdown y publicar en la web con un rendimiento excelente. Desplegado via GitHub Actions en mi servidor." - tags={["astro", "github", "ubuntu"]} - githubLink="https://github.com/arielcostas/costasdev" - /> - - <PortfolioProject - title="MiEntreno (proyecto fin de ciclo)" - summary="Aplicación web para la gestión de entrenamientos deportivos, con una interfaz sencilla y fácil de usar. Desarrollado con ASP.NET Core, Razor Pages y SQL Server." - tags={["dotnet", "azure"]} - githubLink="https://github.com/arielcostas/mientreno" - detailsLink="/portfolio/mientreno/" - /> - - <PortfolioProject - title="Vigo 360" - summary="Blog sobre Vigo y su entorno, orientado principalmente a hablar de movilidad y toponimia. Desarrollado en Go, con base de datos MySQL y desplegado sobre VPS administrado por mí mismo." - tags={["go", "mysql", "ubuntu"]} - githubLink="https://github.com/arielcostas/vigo360" - detailsLink="/portfolio/vigo-360/" - onlineLink="https://vigo360.es" - /> - </section> - - <div class="trajectory-summary"> - <h2>{t.portfolioPage.trajectoryTitle}</h2> - <p>{t.portfolioPage.trajectorySummary}</p> - <a href="/trajectory" class="cta-link">{t.portfolioPage.viewTrajectory} →</a> - </div> -</Layout> - -<style> - section { - display: grid; - grid-template-columns: repeat(auto-fill,minmax(350px,1fr)); - gap: 1.5rem; - } - - .trajectory-summary { - margin-top: 3rem; - background-color: #FFFFFF; - border-radius: 8px; - padding: 1.5rem; - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.08); - border-left: 4px solid hsl(209, 94%, 42%); - } - - .trajectory-summary h2 { - margin-top: 0; - } - - .cta-link { - display: inline-block; - margin-top: 0.5rem; - font-weight: 600; - text-decoration: none; - color: hsl(215, 90%, 30%); - } - - .cta-link:hover { - text-decoration: underline; - } -</style> diff --git a/src/layouts/PortfolioSingleLayout.astro b/src/layouts/PortfolioSingleLayout.astro deleted file mode 100644 index 1922e16..0000000 --- a/src/layouts/PortfolioSingleLayout.astro +++ /dev/null @@ -1,370 +0,0 @@ ---- -import Layout from "@/layouts/Layout.astro"; -import { render } from "astro:content"; -import TechnologyBadge from "@/components/TechnologyBadge.astro"; -import type { InferEntrySchema } from "astro:content"; -import { Icon } from "astro-icon/components"; - -interface Props { - entry: any; -} - -const { entry } = Astro.props; -const data = entry.data as InferEntrySchema<"portfolio">; -const { Content } = await render(entry); ---- - -<Layout title={data.title} description={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>{data.title}</h1> - - <small>Hecho con {data.technologies.map((technology: string) => ( - <TechnologyBadge size="small" code={technology} /> - ))}</small> - - <Content /> - - <div class="project-links"> - {data.githubLink && <a href={data.githubLink} target="_blank" rel="noopener noreferrer" class="project-link"> - <Icon name="tabler:brand-github" class="link-icon"/> - <span>Código en GitHub</span> - </a>} - - {data.onlineLink && <a href={data.onlineLink} target="_blank" rel="noopener noreferrer" class="project-link"> - <Icon name="tabler:external-link" class="link-icon"/> - <span>Ver en línea</span> - </a>} - - {data.demoLink && <a href={data.demoLink} target="_blank" rel="noopener noreferrer" class="project-link"> - <Icon name="tabler:device-laptop" class="link-icon"/> - <span>Ver demo</span> - </a>} - </div> - - {data.images.length > 0 && ( - <h2>Galería</h2> - <section id="project-images"> - {data.images.map((image) => ( - <a href={`${image.src}.png`} target="_blank" rel="noopener noreferrer"> - <picture> - <source - srcset={`${image.src}.webp`} - type="image/webp" - /> - <img src={`${image.src}.png`} alt={image.alt} loading="lazy" /> - </picture> - </a> - ))} - </section> - )} - - <dialog id="largeimage-dialog"> - <div id="largeimage-dialogcontainer"> - <button class="largeimage__nav" aria-label="Previous image" id="largeimage__nav-left"> - <Icon name="tabler:chevron-left" /> - </button> - <div id="largeimage-imagecontainer"> - <img id="largeimage-image" alt="Some alt" /> - </div> - <div id="largeimage-caption">Some caption</div> - <button class="largeimage__nav" aria-label="Next image" id="largeimage__nav-right"> - <Icon name="tabler:chevron-right" /> - </button> - <button id="largeimage-close"><Icon name="tabler:x" /></button> - </div> - </dialog> - -</Layout> - -<script> - document.addEventListener("DOMContentLoaded", () => { - const dialog = document.getElementById("largeimage-dialog") as HTMLDialogElement; - const closeButton = document.getElementById("largeimage-close") as HTMLButtonElement; - const imageElement = document.getElementById("largeimage-image") as HTMLImageElement; - const captionElement = document.getElementById("largeimage-caption") as HTMLDivElement; - const navLeft = document.getElementById("largeimage__nav-left") as HTMLButtonElement; - const navRight = document.getElementById("largeimage__nav-right") as HTMLButtonElement; - const imageLinks = Array.from(document.querySelectorAll("#project-images a")) as HTMLAnchorElement[]; - - const images = imageLinks.map(link => { - const img = link.querySelector("img"); - return { - src: img?.src, - alt: img?.alt - }; - }); - let currentIndex = 0; - - function showImage(index: number) { - if (index < 0 || index >= images.length) return; - currentIndex = index; - const { src, alt } = images[currentIndex]; - if (!imageElement || !captionElement) { - console.error("Image or caption element not found"); - return; - } - imageElement.src = src!; - imageElement.alt = alt!; - captionElement.textContent = alt || "Imagen del proyecto"; - } - - if (!dialog || !closeButton || !imageElement || !captionElement) { - console.error("Dialog or elements not found"); - return; - } - - imageLinks.forEach((link, idx) => { - link.addEventListener("click", (e) => { - e.preventDefault(); - showImage(idx); - dialog.showModal(); - }); - }); - - closeButton.addEventListener("click", () => { - dialog.close(); - }); - - if (navLeft) { - navLeft.addEventListener("click", (e) => { - e.preventDefault(); - showImage((currentIndex - 1 + images.length) % images.length); - }); - } - if (navRight) { - navRight.addEventListener("click", (e) => { - e.preventDefault(); - showImage((currentIndex + 1) % images.length); - }); - } - - dialog.addEventListener("keydown", (e) => { - if (e.key === "ArrowLeft") { - showImage((currentIndex - 1 + images.length) % images.length); - } else if (e.key === "ArrowRight") { - showImage((currentIndex + 1) % images.length); - } else if (e.key === "Escape") { - dialog.close(); - } - }); - - dialog.addEventListener("shown", () => { - dialog.focus(); - }); - - dialog.addEventListener("open", () => { - dialog.focus(); - }); - - dialog.addEventListener("click", (e) => { - if (e.target === dialog) { - dialog.close(); - } - }); - }); -</script> - -<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; - } - - #project-images { - display: flex; - flex-direction: row; - gap: 1.5rem; - margin: 1.5rem 0 2rem; - overflow-x: auto; - padding-bottom: 1rem; - -webkit-overflow-scrolling: touch; - scrollbar-width: thin; - } - - #project-images a { - display: block; - flex: 0 0 auto; - box-shadow: none; - text-decoration: none; - padding: 0; - } - - #project-images picture { - display: block; - overflow: hidden; - border-radius: 0.25rem; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - height: max(20vh, 400px); - } - - #project-images img { - height: 100%; - object-fit: cover; - } - - #project-images a { - position: relative; - } - - .project-links { - display: flex; - gap: 1rem; - flex-wrap: wrap; - margin: 1.5rem 0 2.5rem; - } - - .project-link { - display: inline-flex; - align-items: center; - gap: 0.5rem; - padding: 0.5rem 1.25rem; - border-radius: 2rem; - background-color: #f3f4f6; - color: #333; - font-weight: 600; - text-decoration: none; - box-shadow: none; - transition: all 0.2s ease-in-out; - - &:hover { - background-color: #e5e7eb; - transform: translateY(-2px); - box-shadow: none; - } - - &:focus { - outline: 2px solid $secondary; - background-color: #e5e7eb; - box-shadow: none; - } - - .link-icon { - font-size: 1.2rem; - } - } - - #largeimage-dialog { - padding: 0; - border: none; - background: transparent; - max-width: 100vw; - max-height: 100vh; - margin: auto; - } - - #largeimage-dialog::backdrop { - background: #000c; - } - - #largeimage-dialogcontainer { - position: relative; - display: flex; - flex-direction: column; - gap: 1rem; - height: 100%; - padding: 1.5rem; - } - - #largeimage-imagecontainer { - max-width: 100%; - max-height: calc(100vh - 2rem); - overflow: hidden; - position: relative; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - } - - #largeimage-image { - object-fit: cover; - max-width: 100%; - max-height: calc(100vh - 9rem); - - border-radius: 0.5rem; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - } - - #largeimage-caption { - position: static; - background: #FFFC; - color: #000; - font-size: 1rem; - text-align: center; - border-radius: 0.5rem; - padding: 0.75rem 1rem; - max-width: 100%; - } - - #largeimage-close { - position: absolute; - top: 1rem; - right: 1rem; - width: 2rem; - height: 2rem; - border: none; - background: #fffc; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.5rem; - color: #000; - transition: background-color .2s; - } - - .largeimage__nav { - position: absolute; - top: 50%; - transform: translateY(-50%); - width: 2.5rem; - height: 2.5rem; - border: none; - background: #fffc; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 2rem; - z-index: 2; - color: #000; - transition: background-color .2s; - } - - #largeimage__nav-left { - left: 1rem; - } - #largeimage__nav-right { - right: 1rem; - } - - .largeimage__nav:hover, - #largeimage-close:hover { - background-color: #FFFFFF; - } -</style> |
