Personal site staging.colinozanne.co.uk
portfolio astro

feat: extract project pages to component

finxol.io 2b7467a6 1a88a966

verified
+153 -226
+75
src/components/pages/project.astro
··· 1 + --- 2 + import Layout from "@/layouts/Layout.astro"; 3 + import "@/assets/styles/projects/karr.css"; 4 + import { Icon } from "astro-icon/components"; 5 + import { projects } from "@/data/projects"; 6 + 7 + interface Props { 8 + content: { 9 + projectId: string; 10 + title: string; 11 + subtitle: string; 12 + datePrefix: string; 13 + repoLinkText: string; 14 + }; 15 + } 16 + 17 + const locale = Astro.currentLocale; 18 + 19 + const { content } = Astro.props; 20 + 21 + const project = projects.find((p) => p.id === content.projectId); 22 + if (!project) { 23 + throw new Error(`Project not found: ${content.projectId}`); 24 + } 25 + 26 + const homepage = Astro.url; 27 + homepage.pathname = "/"; 28 + --- 29 + 30 + <Layout> 31 + <article> 32 + <a href={homepage}> 33 + <Icon name="pixel:arrow-alt-circle-left" /> 34 + </a> 35 + 36 + <h2>{content.title}</h2> 37 + 38 + <p class="subtitle">{content.subtitle}</p> 39 + 40 + <div class="boxes"> 41 + <picture style="view-transition-name: project-img"> 42 + <source srcset={project.imgs.webp.src} type="image/webp" /> 43 + <img src={project.imgs.jpg.src} alt={content.title} /> 44 + </picture> 45 + 46 + <div class="container"> 47 + <Icon name={project.dateIcon} /> 48 + <span> 49 + {content.datePrefix} 50 + {project.startDate.toLocaleDateString(locale)} 51 + </span> 52 + </div> 53 + 54 + <div class="container"> 55 + <Icon name={project.runtimeIcon} /> 56 + <span>{project.runtime}</span> 57 + </div> 58 + 59 + <div class="container"> 60 + <Icon name={project.repoIcon} /> 61 + <a 62 + href={project.repoUrl} 63 + class="cover" 64 + target="_blank" 65 + rel="noopener noreferrer" 66 + > 67 + {content.repoLinkText} 68 + <Icon name="pixel:external-link" class="external-link" /> 69 + </a> 70 + </div> 71 + </div> 72 + 73 + <slot /> 74 + </article> 75 + </Layout>
+18
src/data/projects.ts
··· 14 14 }; 15 15 tags: string[]; 16 16 colour?: string; 17 + startDate: Date; 18 + dateIcon: string; 19 + runtime: string; 20 + runtimeIcon: string; 21 + repoUrl: string; 22 + repoIcon: string; 17 23 } 18 24 19 25 export const projects: ProjectMetadata[] = [ ··· 25 31 webp: karrWebp, 26 32 }, 27 33 tags: ["Next.js", "Hono", "OpenAuth", "CI"], 34 + startDate: new Date("10 October 2024"), 35 + dateIcon: "tabler:brand-git", 36 + runtime: "NodeJS", 37 + runtimeIcon: "tabler:brand-nodejs", 38 + repoUrl: "https://github.com/karr-mobi/karr", 39 + repoIcon: "tabler:brand-github", 28 40 }, 29 41 { 30 42 id: "blog", ··· 35 47 }, 36 48 tags: ["Nuxt.js", "Markdown"], 37 49 colour: "--yellow-300", 50 + startDate: new Date("24 April 2022"), 51 + dateIcon: "tabler:calendar-smile", 52 + runtime: "Deno", 53 + runtimeIcon: "tabler:brand-deno", 54 + repoUrl: "https://tangled.org/finxol.io/blog", 55 + repoIcon: "tabler:brand-git", 38 56 }, 39 57 ];
+14 -55
src/pages/en/projects/blog.astro
··· 1 1 --- 2 - import Layout from "@/layouts/Layout.astro"; 3 - import "@/assets/styles/projects/karr.css"; 4 - import { Icon } from "astro-icon/components"; 2 + import ProjectPage from "@/components/pages/project.astro"; 5 3 6 - import blogJpg from "@/assets/img/finxol_blog_home.jpg"; 7 - import blogWebp from "@/assets/img/finxol_blog_home.webp"; 4 + const content = { 5 + projectId: "blog", 6 + title: "Blog", 7 + subtitle: "Personal technical blog", 8 + datePrefix: "Since", 9 + repoLinkText: "Tangled repo", 10 + }; 8 11 --- 9 12 10 - <Layout> 11 - <article> 12 - <a href="/"> 13 - <Icon name="pixel:arrow-alt-circle-left" /> 14 - </a> 15 - 16 - <h2>Blog</h2> 17 - 18 - <p class="subtitle">Personal technical blog</p> 19 - 20 - <div class="boxes"> 21 - <picture style="view-transition-name: project-img"> 22 - <source srcset={blogWebp.src} type="image/webp" /> 23 - <img src={blogJpg.src} alt="Blog" /> 24 - </picture> 25 - 26 - <div class="container"> 27 - <Icon name="tabler:calendar-smile" /> 28 - <span> 29 - Since { 30 - new Date("24 April 2022").toLocaleDateString("en-GB") 31 - } 32 - </span> 33 - </div> 34 - 35 - <div class="container"> 36 - <Icon name="tabler:brand-deno" /> 37 - <span> Deno </span> 38 - </div> 39 - 40 - <div class="container"> 41 - <Icon name="tabler:brand-git" /> 42 - <a 43 - href="https://tangled.org/finxol.io/blog" 44 - class="cover" 45 - target="_blank" 46 - rel="noopener noreferrer" 47 - > 48 - Tangled repo 49 - <Icon name="pixel:external-link" class="external-link" /> 50 - </a> 51 - </div> 52 - </div> 53 - 54 - <p class="description"> 55 - On this blog, I write about various topics, including web 56 - development and technology. 57 - </p> 58 - </article> 59 - </Layout> 13 + <ProjectPage content={content}> 14 + <p class="description"> 15 + On this blog, I write about various topics, including web development 16 + and technology. 17 + </p> 18 + </ProjectPage>
+16 -55
src/pages/en/projects/karr.astro
··· 1 1 --- 2 - import Layout from "@/layouts/Layout.astro"; 3 - import "@/assets/styles/projects/karr.css"; 4 - import { Icon } from "astro-icon/components"; 2 + import ProjectPage from "@/components/pages/project.astro"; 5 3 6 - import karrJpg from "@/assets/img/karr_demo.jpg"; 7 - import karrWebp from "@/assets/img/karr_demo.webp"; 4 + const content = { 5 + projectId: "karr", 6 + title: "Karr", 7 + subtitle: "Federated carpool platform for companies", 8 + datePrefix: "Since", 9 + repoLinkText: "Github repo", 10 + }; 8 11 --- 9 12 10 - <Layout> 11 - <article> 12 - <a href="/"> 13 - <Icon name="pixel:arrow-alt-circle-left" /> 14 - </a> 15 - 16 - <h2>Karr</h2> 17 - 18 - <p class="subtitle">Federated carpool platform for companies</p> 19 - 20 - <div class="boxes"> 21 - <picture style="view-transition-name: project-img"> 22 - <source srcset={karrWebp.src} type="image/webp" /> 23 - <img src={karrJpg.src} alt="Karr" /> 24 - </picture> 25 - 26 - <div class="container"> 27 - <Icon name="tabler:brand-git" /> 28 - <span> 29 - Since {new Date("10 October 2024").toLocaleDateString()} 30 - </span> 31 - </div> 32 - 33 - <div class="container"> 34 - <Icon name="tabler:brand-nodejs" /> 35 - <span> NodeJS </span> 36 - </div> 37 - 38 - <div class="container"> 39 - <Icon name="tabler:brand-github" /> 40 - <a 41 - href="https://github.com/karr-mobi/karr" 42 - class="cover" 43 - target="_blank" 44 - rel="noopener noreferrer" 45 - > 46 - Github repo 47 - <Icon name="pixel:external-link" class="external-link" /> 48 - </a> 49 - </div> 50 - </div> 51 - 52 - <p class="description"> 53 - This entrepreneurial project was carried out for 5 months with 54 - <a href="https://www.pepitebretagne.fr/"> Pépite Bretagne</a>. The 55 - project was discontinued after a market study revealed a 56 - well-established competition, already subsidized by public funds. 57 - </p> 58 - </article> 59 - </Layout> 13 + <ProjectPage content={content}> 14 + <p class="description"> 15 + This entrepreneurial project was carried out for 5 months with 16 + <a href="https://www.pepitebretagne.fr/">Pépite Bretagne</a>. The 17 + project was discontinued after a market study revealed a 18 + well-established competition, already subsidized by public funds. 19 + </p> 20 + </ProjectPage>
+14 -55
src/pages/fr/projects/blog.astro
··· 1 1 --- 2 - import Layout from "@/layouts/Layout.astro"; 3 - import "@/assets/styles/projects/karr.css"; 4 - import { Icon } from "astro-icon/components"; 2 + import ProjectPage from "@/components/pages/project.astro"; 5 3 6 - import blogJpg from "@/assets/img/finxol_blog_home.jpg"; 7 - import blogWebp from "@/assets/img/finxol_blog_home.webp"; 4 + const content = { 5 + projectId: "blog", 6 + title: "Blog", 7 + subtitle: "Blog technique personnel", 8 + datePrefix: "Depuis le", 9 + repoLinkText: "Repo Tangled", 10 + }; 8 11 --- 9 12 10 - <Layout> 11 - <article> 12 - <a href="/"> 13 - <Icon name="pixel:arrow-alt-circle-left" /> 14 - </a> 15 - 16 - <h2>Blog</h2> 17 - 18 - <p class="subtitle">Blog technique personnel</p> 19 - 20 - <div class="boxes"> 21 - <picture style="view-transition-name: project-img"> 22 - <source srcset={blogWebp.src} type="image/webp" /> 23 - <img src={blogJpg.src} alt="Blog" /> 24 - </picture> 25 - 26 - <div class="container"> 27 - <Icon name="tabler:calendar-smile" /> 28 - <span> 29 - Depuis le { 30 - new Date("24 April 2022").toLocaleDateString("fr-FR") 31 - } 32 - </span> 33 - </div> 34 - 35 - <div class="container"> 36 - <Icon name="tabler:brand-deno" /> 37 - <span> Deno </span> 38 - </div> 39 - 40 - <div class="container"> 41 - <Icon name="tabler:brand-git" /> 42 - <a 43 - href="https://tangled.org/finxol.io/blog" 44 - class="cover" 45 - target="_blank" 46 - rel="noopener noreferrer" 47 - > 48 - Repo Tangled 49 - <Icon name="pixel:external-link" class="external-link" /> 50 - </a> 51 - </div> 52 - </div> 53 - 54 - <p class="description"> 55 - Sur ce blog, j'écris sur des sujets variés, notamment sur le 56 - développement web, et la technologie. 57 - </p> 58 - </article> 59 - </Layout> 13 + <ProjectPage content={content}> 14 + <p class="description"> 15 + Sur ce blog, j'écris sur des sujets variés, notamment sur le 16 + développement web, et la technologie. 17 + </p> 18 + </ProjectPage>
+16 -61
src/pages/fr/projects/karr.astro
··· 1 1 --- 2 - import Layout from "@/layouts/Layout.astro"; 3 - import "@/assets/styles/projects/karr.css"; 4 - import { Icon } from "astro-icon/components"; 5 - 6 - import karrJpg from "@/assets/img/karr_demo.jpg"; 7 - import karrWebp from "@/assets/img/karr_demo.webp"; 2 + import ProjectPage from "@/components/pages/project.astro"; 8 3 9 - const homepage = Astro.url; 10 - homepage.pathname = "/"; 4 + const content = { 5 + projectId: "karr", 6 + title: "Karr", 7 + subtitle: "Plateforme de covoiturage fédérée pour entreprises", 8 + datePrefix: "Depuis le", 9 + repoLinkText: "Github repo", 10 + }; 11 11 --- 12 12 13 - <Layout> 14 - <article> 15 - <a href={homepage}> 16 - <Icon name="pixel:arrow-alt-circle-left" /> 17 - </a> 18 - 19 - <h2>Karr</h2> 20 - 21 - <p class="subtitle"> 22 - Plateforme de covoiturage fédérée pour entreprises 23 - </p> 24 - 25 - <div class="boxes"> 26 - <picture style="view-transition-name: project-img"> 27 - <source srcset={karrWebp.src} type="image/webp" /> 28 - <img src={karrJpg.src} alt="Karr" /> 29 - </picture> 30 - 31 - <div class="container"> 32 - <Icon name="tabler:brand-git" /> 33 - <span> 34 - Depuis le {new Date("10 October 2024").toLocaleDateString()} 35 - </span> 36 - </div> 37 - 38 - <div class="container"> 39 - <Icon name="tabler:brand-nodejs" /> 40 - <span> NodeJS </span> 41 - </div> 42 - 43 - <div class="container"> 44 - <Icon name="tabler:brand-github" /> 45 - <a 46 - href="https://github.com/karr-mobi/karr" 47 - class="cover" 48 - target="_blank" 49 - rel="noopener noreferrer" 50 - > 51 - Github repo 52 - <Icon name="pixel:external-link" class="external-link" /> 53 - </a> 54 - </div> 55 - </div> 56 - 57 - <p class="description"> 58 - Ce projet entrepreneurial a été porté pendant 5 mois avec 59 - <a href="https://www.pepitebretagne.fr/"> Pépite Bretagne</a>. 60 - L'arrêt du projet a été décidé après une étude de marché révélant 61 - une concurrence déjà fortement présente et subventionnée par des 62 - fonds publics. 63 - </p> 64 - </article> 65 - </Layout> 13 + <ProjectPage content={content}> 14 + <p class="description"> 15 + Ce projet entrepreneurial a été porté pendant 5 mois avec 16 + <a href="https://www.pepitebretagne.fr/">Pépite Bretagne</a>. L'arrêt du 17 + projet a été décidé après une étude de marché révélant une concurrence 18 + déjà fortement présente et subventionnée par des fonds publics. 19 + </p> 20 + </ProjectPage>