Personal site staging.colinozanne.co.uk
portfolio astro

feat: add education

finxol.io f72a0376 ffd96077

verified
+227 -5
+92 -3
src/assets/styles/index.css
··· 13 13 "content-languages content-blog" 14 14 "contact contact" 15 15 "title-projects title-projects" 16 - "content-projects content-projects"; 16 + "content-projects content-projects" 17 + "title-education title-education" 18 + "content-education content-education"; 17 19 gap: var(--spacing); 18 20 } 19 21 20 - section.title-projects { 21 - grid-area: title-projects; 22 + section.section-title { 22 23 display: flex; 23 24 flex-direction: row; 24 25 align-items: center; ··· 30 31 31 32 @media screen and (max-width: 768px) { 32 33 flex-direction: column; 34 + } 35 + 36 + &.title-projects { 37 + grid-area: title-projects; 38 + } 39 + 40 + &.title-education { 41 + grid-area: title-education; 33 42 } 34 43 35 44 & > * { ··· 279 288 text-align: center; 280 289 text-wrap: balance; 281 290 } 291 + } 292 + } 293 + } 294 + 295 + section.content-education { 296 + grid-area: content-education; 297 + display: flex; 298 + flex-direction: column; 299 + gap: 0; 300 + margin-inline: calc(var(--spacing) * 2); 301 + padding-block-end: var(--spacing); 302 + 303 + .education-item { 304 + display: grid; 305 + grid-template-columns: auto 1fr; 306 + gap: calc(var(--spacing) * 1.5); 307 + 308 + @media screen and (max-width: 768px) { 309 + gap: var(--spacing); 310 + } 311 + } 312 + 313 + .education-timeline { 314 + display: flex; 315 + flex-direction: column; 316 + align-items: center; 317 + padding-top: 0.35rem; 318 + } 319 + 320 + .education-dot { 321 + width: 0.75rem; 322 + height: 0.75rem; 323 + border-radius: 50%; 324 + background-color: var(--primary); 325 + flex-shrink: 0; 326 + } 327 + 328 + .education-line { 329 + width: 2px; 330 + flex-grow: 1; 331 + background-color: oklch(from var(--primary) l c h / 0.4); 332 + margin-block: 0.5rem; 333 + } 334 + 335 + .education-content { 336 + padding-block-end: calc(var(--spacing) * 2); 337 + 338 + h4 { 339 + margin: 0; 340 + font-size: var(--size-1); 341 + font-weight: bold; 342 + color: var(--foreground); 343 + } 344 + 345 + p { 346 + margin: 0; 347 + margin-block-start: 0.5rem; 348 + font-size: var(--size-0); 349 + color: oklch(from var(--foreground) l c h / 0.8); 350 + } 351 + } 352 + 353 + .education-date { 354 + display: inline-block; 355 + font-size: var(--size--1); 356 + font-weight: 500; 357 + color: var(--primary); 358 + margin-block-end: 0.25rem; 359 + } 360 + 361 + .education-notes { 362 + margin: 0; 363 + margin-block-start: 0.75rem; 364 + padding-inline-start: 1.25rem; 365 + list-style-type: disc; 366 + 367 + li { 368 + font-size: var(--size--1); 369 + color: oklch(from var(--foreground) l c h / 0.7); 370 + margin-block: 0.25rem; 282 371 } 283 372 } 284 373 }
+51 -2
src/components/pages/index.astro
··· 3 3 import "@/assets/styles/index.css"; 4 4 import { Icon } from "astro-icon/components"; 5 5 import { projects } from "@/data/projects"; 6 + import { education } from "@/data/education"; 6 7 import { config } from "@/config"; 7 8 import type { Locale } from "@/hooks/useLocale.astro"; 8 9 import Customise from "../customise.astro"; ··· 29 30 additionalProjectsTitle: string; 30 31 additionalProjectsDescription: string; 31 32 }; 33 + educationSection: { 34 + title: string; 35 + description: string; 36 + }; 32 37 }; 33 38 } 34 39 35 40 const locale = (Astro.currentLocale as Locale) ?? config.defaultLocale; 36 41 37 42 const { 38 - content: { intro, languages, blogSection, contact, projectsSection }, 43 + content: { 44 + intro, 45 + languages, 46 + blogSection, 47 + contact, 48 + projectsSection, 49 + educationSection, 50 + }, 39 51 } = Astro.props; 40 52 41 53 const oddNumberProjects = projects.length % 2 !== 0; ··· 152 164 </div> 153 165 </section> 154 166 155 - <section class="title-projects"> 167 + <section class="section-title title-projects"> 156 168 <aside> 157 169 <Icon name="pixel:code-block-solid" /> 158 170 </aside> ··· 206 218 </div> 207 219 </div> 208 220 ) 221 + } 222 + </section> 223 + 224 + <section class="section-title title-education"> 225 + <aside> 226 + <Icon name="lucide:graduation-cap" /> 227 + </aside> 228 + <h3>{educationSection.title}</h3> 229 + <p> 230 + {educationSection.description} 231 + </p> 232 + </section> 233 + 234 + <section class="content-education"> 235 + { 236 + education.map((item, index) => ( 237 + <div class="education-item"> 238 + <div class="education-timeline"> 239 + <span class="education-dot" /> 240 + {index < education.length - 1 && ( 241 + <span class="education-line" /> 242 + )} 243 + </div> 244 + <div class="education-content"> 245 + <span class="education-date">{item.date}</span> 246 + <h4>{item.title[locale]}</h4> 247 + <p>{item.description[locale]}</p> 248 + {item.notes && item.notes.length > 0 && ( 249 + <ul class="education-notes"> 250 + {item.notes.map((note) => ( 251 + <li>{note[locale]}</li> 252 + ))} 253 + </ul> 254 + )} 255 + </div> 256 + </div> 257 + )) 209 258 } 210 259 </section> 211 260 </article>
+74
src/data/education.ts
··· 1 + import { Localised } from "./projects.ts"; 2 + 3 + interface Education { 4 + title: Localised; 5 + description: Localised; 6 + date: string; 7 + notes?: Localised[]; 8 + } 9 + 10 + export const education: Education[] = [ 11 + { 12 + title: { 13 + "en": "Master's in Computer Science", 14 + "fr": "Master en Informatique", 15 + }, 16 + description: { 17 + "en": "ISTIC — Université de Rennes", 18 + "fr": "ISTIC — Université de Rennes", 19 + }, 20 + date: "2025 - 2027", 21 + notes: [ 22 + { 23 + "en": "VP of Digital Tools @ FARE", 24 + "fr": "VP Outils Numériques @ FARE", 25 + }, 26 + ], 27 + }, 28 + { 29 + title: { 30 + "en": "Bachelor's in Computer Science", 31 + "fr": "Licence en Informatique", 32 + }, 33 + description: { 34 + "en": "ISTIC — Université de Rennes", 35 + "fr": "ISTIC — Université de Rennes", 36 + }, 37 + date: "2024 - 2025", 38 + }, 39 + { 40 + title: { 41 + "en": "Erasmus semester in Joensuu, Finland", 42 + "fr": "Semestre Erasmus à Joensuu, Finlande", 43 + }, 44 + description: { 45 + "en": "University of Eastern Finland", 46 + "fr": "University of Eastern Finland", 47 + }, 48 + date: "2023", 49 + notes: [ 50 + { 51 + "en": "Active member of the International Student Association (ESN)", 52 + "fr": 53 + "Membre actif de l'Association des Étudiants Internationaux (ESN)", 54 + }, 55 + ], 56 + }, 57 + { 58 + title: { 59 + "en": "DUT in Computer Science", 60 + "fr": "DUT Informatique", 61 + }, 62 + description: { 63 + "en": "IUT de Vannes, Brittany", 64 + "fr": "IUT de Vannes", 65 + }, 66 + date: "2021 - 2023", 67 + notes: [ 68 + { 69 + "en": "Member of the Student Council", 70 + "fr": "Membre du Bureau des Étudiants", 71 + }, 72 + ], 73 + }, 74 + ];
+5
src/pages/en/index.astro
··· 23 23 additionalProjectsDescription: 24 24 "I'll keep adding the best of my projects as I get building", 25 25 }, 26 + educationSection: { 27 + title: "Education", 28 + description: 29 + "I'm currently studying computer science at the University of Rennes.", 30 + }, 26 31 }; 27 32 --- 28 33
+5
src/pages/fr/index.astro
··· 24 24 additionalProjectsDescription: 25 25 "Je continuerai à ajouter mes meilleurs projets.", 26 26 }, 27 + educationSection: { 28 + title: "Éducation", 29 + description: 30 + "Je suis actuellement étudiant en informatique à l'Université de Rennes.", 31 + }, 27 32 }; 28 33 --- 29 34