diff options
Diffstat (limited to 'src/layouts')
| -rw-r--r-- | src/layouts/ContactPageLayout.astro | 99 | ||||
| -rw-r--r-- | src/layouts/HomePageLayout.astro | 62 | ||||
| -rw-r--r-- | src/layouts/Layout.astro | 28 | ||||
| -rw-r--r-- | src/layouts/PortfolioPageLayout.astro | 113 | ||||
| -rw-r--r-- | src/layouts/TrajectoryPageLayout.astro | 81 |
5 files changed, 375 insertions, 8 deletions
diff --git a/src/layouts/ContactPageLayout.astro b/src/layouts/ContactPageLayout.astro new file mode 100644 index 0000000..3b3c278 --- /dev/null +++ b/src/layouts/ContactPageLayout.astro @@ -0,0 +1,99 @@ +--- +import { useTranslations } from "../i18n"; +import Layout from "./Layout.astro"; + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "https://schema.org", + "@type": "ContactPage", + url: "https://www.costas.dev/contact", + headline: t.contactPage.headline, +}; +--- + +<Layout title={t.contactPage.title} description={t.contactPage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.contactPage.headline}</h1> + + <noscript> + <div role="alert" class="warning"> + {t.contactPage.enableJs} + </div> + </noscript> + + <p set:html={t.contactPage.intro} /> + + <p>{t.contactPage.socialMedia}</p> + + <dl> + <dt>GitHub</dt> + <dd><a href="https://github.com/arielcostas">@arielcostas</a></dd> + <dt>LinkedIn</dt> + <dd> + <a href="https://www.linkedin.com/in/ariel-costas/" + >/in/ariel-costas</a> + </dd> + <dt>BlueSky</dt> + <dd><a href="https://bsky.app/profile/costas.dev">@costas.dev</a></dd> + </dl> +</Layout> + +<script> + const encryptedEmail = "LygNLiMmFRo/GlQZaFIWBA=="; + const encryptedPhoneNumber = "ZWlQfX1QT0Z+XgVd"; + const key = "NZdKOfvuLn5jF6sryF0Q"; + + const emailAddrLink = document.getElementById( + "email-addr", + ) as HTMLAnchorElement; + const phoneNumberLink = document.getElementById( + "phone-number", + ) as HTMLAnchorElement; + + (() => { + if (emailAddrLink == null || phoneNumberLink == null) { + return; + } + + const emailAddress = xorData(encryptedEmail, key); + const phoneNumber = xorData(encryptedPhoneNumber, key); + + emailAddrLink.href = `mailto:${emailAddress}`; + emailAddrLink.textContent = emailAddress; + + phoneNumberLink.href = `tel:${phoneNumber}`; + phoneNumberLink.textContent = phoneNumber; + })(); + + function xorData(data: string, key: string): string { + let actualData = atob(data); + let actualKey = key; + const keyLength = key.length; + const dataLength = actualData.length; + const result = new Array(dataLength); + + // If the key is 12 characters but the data is 30 characters, the key should be repeated 3 times and truncated to 30 characters + if (keyLength < dataLength) { + actualKey = key + .repeat(Math.ceil(dataLength / keyLength)) + .substring(0, dataLength); + } else if (keyLength > dataLength) { + actualKey = key.substring(0, dataLength); + } + + for (let i = 0; i < dataLength; i++) { + result[i] = String.fromCharCode( + actualData.charCodeAt(i) ^ actualKey.charCodeAt(i), + ); + } + + return result.join(""); + } +</script> diff --git a/src/layouts/HomePageLayout.astro b/src/layouts/HomePageLayout.astro new file mode 100644 index 0000000..146eaec --- /dev/null +++ b/src/layouts/HomePageLayout.astro @@ -0,0 +1,62 @@ +--- +import { getCollection } from "astro:content"; +import Layout from "./Layout.astro"; +import { useTranslations } from "../i18n"; + +const blogCollection = (await getCollection("blog")).sort((a, b) => { + return b.data.publishedAt.getTime() - a.data.publishedAt.getTime(); +}); + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "http://schema.org", + "@type": "WebSite", + id: "https://www.costas.dev/", + url: "https://www.costas.dev/", + headline: t.homePage.title, +}; +--- + +<Layout title={t.homePage.title} description={t.homePage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.homePage.title}</h1> + <p>{t.homePage.welcome}</p> + + <h2>{t.homePage.whoAmI}</h2> + <p>{t.homePage.whoAmIDesc}</p> + <a href="/trajectory">{t.homePage.moreAboutMe}</a> + + <h2>{t.homePage.whatIDo}</h2> + <p>{t.homePage.whatIDoDesc}</p> + <a href="/portfolio">{t.homePage.myPortfolio}</a> + + <h2>{t.homePage.latestBlogPosts}</h2> + <ul> + { + blogCollection.slice(0, 5).map((p) => { + const date = Intl.DateTimeFormat(Astro.currentLocale, { + day: "2-digit", + month: "short", + year: "numeric", + }).format(p.data.publishedAt); + return ( + <li> + <time datetime={p.data.publishedAt.toISOString()}> + {date} + </time> + <a href={`/blog/${p.id}`}>{p.data.title}</a> + </li> + ); + }) + } + </ul> + <a href="/blog">{t.homePage.viewAllPosts}</a> + +</Layout> diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 4952d55..eda1716 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -13,7 +13,7 @@ const { title, description } = Astro.props; --- <!doctype html> -<html lang="es"> +<html lang={Astro.currentLocale}> <head> <meta charset="UTF-8" /> <meta name="description" content={description} /> @@ -53,6 +53,7 @@ const { title, description } = Astro.props; <style is:global lang="scss"> @use "../../styles/shared.scss" as *; + @use "sass:color"; html, body { @@ -82,7 +83,7 @@ const { title, description } = Astro.props; } *::selection { - background-color: transparentize($accent, 0.85); + background-color: color.adjust($accent, $alpha: -0.85); } li > time { @@ -93,12 +94,17 @@ const { title, description } = Astro.props; padding: 1rem; margin-block: 1rem; border-radius: 0.5rem; - - box-shadow: 0 0 0 1px $accent; - + &.note { background-color: $noteBackground; color: $noteText; + box-shadow: 0 0 0 1px $noteText; + } + + &.warning { + background-color: $warningBackground; + color: $warningText; + box-shadow: 0 0 0 1px $warningText; } } @@ -132,10 +138,15 @@ const { title, description } = Astro.props; } } - main a, footer a { + main a { color: $accentDark; - transition: color 0.2s ease-in-out, - box-shadow 0.2s ease-in-out; + } + + footer a { + color: $accentLight; + } + + main a, footer a { text-decoration: none; padding: 0.1rem; box-shadow: 0 1px $accent; @@ -145,6 +156,7 @@ const { title, description } = Astro.props; } &:focus { + color: $accentDark; outline: none; background-color: $secondary; box-shadow: 0 4px #0b0c0c; diff --git a/src/layouts/PortfolioPageLayout.astro b/src/layouts/PortfolioPageLayout.astro new file mode 100644 index 0000000..0ade4ba --- /dev/null +++ b/src/layouts/PortfolioPageLayout.astro @@ -0,0 +1,113 @@ +--- +import Layout from "./Layout.astro"; +import { useTranslations } from "../i18n"; +import TechnologyBadge from "../partials/TechnologyBadge.astro"; + +const t = useTranslations(Astro.currentLocale); + +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)} + ></script> + + <h1>{t.portfolioPage.headline}</h1> + + <p set:html={t.portfolioPage.intro} /> + + <h2>{t.portfolioPage.freelanceTitle}</h2> + + <p>{t.portfolioPage.freelanceDesc}</p> + + <section> + <article> + <h3>{t.portfolioPage.orderExtractorTitle}</h3> + + <p set:html={t.portfolioPage.orderExtractorDesc} /> + + <TechnologyBadge code="java" /> + <TechnologyBadge code="windows" /> + </article> + + <article> + <h3>{t.portfolioPage.touristInfoTitle}</h3> + + <p set:html={t.portfolioPage.touristInfoDesc} /> + + <TechnologyBadge code="php" /> + <TechnologyBadge code="mysql" /> + </article> + + <article> + <h3>{t.portfolioPage.wpConsultingTitle}</h3> + + <p set:html={t.portfolioPage.wpConsultingDesc} /> + + <TechnologyBadge code="php" /> + </article> + </section> + + <h2>{t.portfolioPage.ownProjectsTitle}</h2> + + <p>{t.portfolioPage.ownProjectsDesc}</p> + + <section> + <article> + <h3>{t.portfolioPage.personalWebTitle}</h3> + + <p>{t.portfolioPage.personalWebDesc}</p> + + <TechnologyBadge code="astro" /> + <TechnologyBadge code="azure" /> + </article> + + <article> + <h3>{t.portfolioPage.mientrenoTitle}</h3> + + <p set:html={t.portfolioPage.mientrenoDesc} /> + + <TechnologyBadge code="dotnet" /> + <TechnologyBadge code="sqlserver" /> + <TechnologyBadge code="azure" /> + <TechnologyBadge code="rabbitmq" /> + </article> + + <article> + <h3>{t.portfolioPage.vigo360Title}</h3> + + <p set:html={t.portfolioPage.vigo360Desc} /> + + <TechnologyBadge code="go" /> + <TechnologyBadge code="mysql" /> + <TechnologyBadge code="linux" /> + </article> + </section> +</Layout> + +<style> + section { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + gap: 1rem; + } + + article { + padding: 1rem; + border: 1px solid var(--accent); + border-radius: 0.5rem; + } + + article h3 { + margin-top: 0; + } +</style>
\ No newline at end of file diff --git a/src/layouts/TrajectoryPageLayout.astro b/src/layouts/TrajectoryPageLayout.astro new file mode 100644 index 0000000..1739a32 --- /dev/null +++ b/src/layouts/TrajectoryPageLayout.astro @@ -0,0 +1,81 @@ +--- +import { useTranslations } from "../i18n"; +import Layout from "./Layout.astro"; + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "https://schema.org", + "@type": "WebPage", + url: "https://www.costas.dev/trajectory", + headline: t.trajectoryPage.headline, +}; +--- + +<Layout title={t.trajectoryPage.title} description={t.trajectoryPage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.trajectoryPage.headline}</h1> + + <p>{t.trajectoryPage.intro}</p> + + <h2>{t.trajectoryPage.techTitle}</h2> + + <p>{t.trajectoryPage.techDescription1}</p> + + <p>{t.trajectoryPage.techDescription2}</p> + + <h2>{t.trajectoryPage.educationTitle}</h2> + + <ul> + <li> + <strong>{t.trajectoryPage.efsetCert1}</strong> + {t.trajectoryPage.efsetCert2} <a + href="https://cert.efset.org/es/Yxzc9L" + >{t.trajectoryPage.viewCertificate}</a + > + </li> + + <li> + <strong>{t.trajectoryPage.azureDeveloperCert1}</strong> + {t.trajectoryPage.azureDeveloperCert2} <a + href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/E15072607CCF2DA9?sharingId=149A1CD9C13790F4" + >{t.trajectoryPage.viewCredential}</a + >. + </li> + + <li> + <strong>{t.trajectoryPage.azureDevOpsCert1}</strong> + {t.trajectoryPage.azureDevOpsCert2} <a + href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/5FB94876A1701595?sharingId=149A1CD9C13790F4" + >{t.trajectoryPage.viewCredential}</a + > + </li> + + <li> + <strong>{t.trajectoryPage.higherTechCert1}</strong> + {t.trajectoryPage.higherTechCert2} <a href="https://iesteis.es/">{t.trajectoryPage.higherTechCert3}</a> {t.trajectoryPage.higherTechCert4} + </li> + </ul> + + <h2>{t.trajectoryPage.experienceTitle}</h2> + + <h3>{t.trajectoryPage.estelaria1}</h3> + + <p>{t.trajectoryPage.estelaria2}</p> + + <p>{t.trajectoryPage.estelaria3}</p> + + <h3>{t.trajectoryPage.polygon1}</h3> + + <p>{t.trajectoryPage.polygon2}</p> + + <h2>{t.trajectoryPage.projectsTitle}</h2> + + <p set:html={t.trajectoryPage.projectsDescription} /> +</Layout> |
