From a596d1c44335d0fe660665a01406c5d9da05422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20LUDWIG?= Date: Wed, 31 Jul 2024 22:27:51 +0200 Subject: [PATCH] feat: components structure Curriculum Vitae --- .../app/[locale]/curriculum-vitae/page.tsx | 7 +- packages/config-tailwind/styles.css | 224 ++++++++++++++++++ .../curriculum-vitae.fr-FR.legacy.jsonc | 181 ++++++++++++++ packages/i18n/src/translations/en-US.json | 111 ++++++++- packages/i18n/src/translations/fr-FR.json | 111 ++++++++- packages/ui/package.json | 1 + .../CurriculumVitae.stories.tsx | 16 ++ .../src/CurriculumVitae/CurriculumVitae.tsx | 40 ++++ .../CurriculumVitae/CurriculumVitaeAbout.tsx | 19 ++ .../CurriculumVitaeEducation.tsx | 21 ++ .../CurriculumVitaeInterests.tsx | 21 ++ .../CurriculumVitaeProfile.tsx | 55 +++++ .../CurriculumVitaeSection.tsx | 23 ++ .../CurriculumVitae/CurriculumVitaeSkills.tsx | 21 ++ .../CurriculumVitae/CurriculumVitaeWork.tsx | 19 ++ .../ui/src/Design/Button/Button.stories.tsx | 2 +- .../ui/src/Home/About/AboutList/AboutItem.tsx | 2 +- .../About/AboutList/AboutItemBirthDate.tsx | 27 --- .../ui/src/Home/About/AboutList/AboutList.tsx | 7 +- .../ui/src/Home/About/AboutList/BirthDate.tsx | 21 ++ 20 files changed, 891 insertions(+), 38 deletions(-) create mode 100644 packages/i18n/src/translations/curriculum-vitae.fr-FR.legacy.jsonc create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitae.stories.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitae.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeAbout.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeEducation.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeInterests.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeProfile.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeSection.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeSkills.tsx create mode 100644 packages/ui/src/CurriculumVitae/CurriculumVitaeWork.tsx delete mode 100644 packages/ui/src/Home/About/AboutList/AboutItemBirthDate.tsx create mode 100644 packages/ui/src/Home/About/AboutList/BirthDate.tsx diff --git a/apps/website/app/[locale]/curriculum-vitae/page.tsx b/apps/website/app/[locale]/curriculum-vitae/page.tsx index 6987e28..2a972ea 100644 --- a/apps/website/app/[locale]/curriculum-vitae/page.tsx +++ b/apps/website/app/[locale]/curriculum-vitae/page.tsx @@ -1,4 +1,5 @@ import type { LocaleProps } from "@repo/i18n/config" +import { CurriculumVitae } from "@repo/ui/CurriculumVitae" import { unstable_setRequestLocale } from "next-intl/server" interface CurriculumVitaeProps extends LocaleProps {} @@ -9,11 +10,7 @@ const CurriculumVitaePage: React.FC = (props) => { // Enable static rendering unstable_setRequestLocale(params.locale) - return ( -
-

CurriculumVitae

-
- ) + return } export default CurriculumVitaePage diff --git a/packages/config-tailwind/styles.css b/packages/config-tailwind/styles.css index 2389325..b6b4686 100644 --- a/packages/config-tailwind/styles.css +++ b/packages/config-tailwind/styles.css @@ -160,3 +160,227 @@ code .line:last-child { white-space: normal !important; width: 100% !important; } + +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.curriculum-vitae { + background: #f0f0f0; + color: #333; + line-height: 1.42857143; + font-size: 14px; + + hr { + margin-top: 15px; + margin-bottom: 15px; + border: 0; + border-top: 1px solid #eee; + } + p { + margin: 0; + } + strong { + font-weight: 600; + } + a { + color: #337ab7; + text-decoration: none; + } + a:focus, + a:hover { + color: #23527c; + text-decoration: underline; + } + .link-disguise { + color: inherit; + } + .link-disguise:hover { + color: inherit; + } + .h1, + .h2, + .h3, + h1, + h2, + h3 { + margin-top: 20px; + margin-bottom: 10px; + } + .h4, + .h5, + .h6, + h4, + h5, + h6 { + margin-top: 10px; + margin-bottom: 10px; + } + .h1, + .h2, + .h3, + .h4, + .h5, + .h6, + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; + } + .h3, + h3 { + font-size: 24px; + } + .h4, + h4 { + font-size: 18px; + } + .h5, + h5 { + font-size: 14px; + } + .row { + margin-right: -15px; + margin-left: -15px; + } + .clear-margin { + margin: 0; + } + .relative { + position: relative; + } + .center-block { + display: block; + margin-right: auto; + margin-left: auto; + } + .text-muted { + color: #777; + } + .text-uppercase { + text-transform: uppercase; + } + .list-unstyled { + padding-left: 0; + list-style: none; + } + + .main { + padding: 5px; + } + .title { + font-weight: 600; + } + + .profile-card-wrapper { + position: relative; + } + + .card-wrapper { + float: none !important; + padding: 5px; + } + + .profile-card-wrapper .profile-card { + padding: 10px; + } + + .card { + background: white; + border-radius: 3px; + padding: 10px 0; + } + .profile-pic { + padding: 10px 0; + } + .profile-pic img { + width: 100px; + height: 100px; + border-radius: 50%; + vertical-align: middle; + border: 0; + } + .contact-details { + display: flex; + justify-content: center; + } + .contact-details .detail { + position: relative; + min-height: 1px; + padding: 10px; + } + .social-links { + line-height: 2.5; + } + .experience-description { + margin-top: 10px; + } + + .background-details .detail { + display: table; + } + .background-details .detail .icon, + .background-details .detail .info { + display: table-cell; + } + .background-details .detail .icon { + color: #707070; + } + .background-details .detail .icon { + min-width: 45px; + max-width: 45px; + text-align: center; + } + .icon img { + width: 20px; + height: 20px; + } + .background-details .detail .mobile-title { + display: none; + } + .card-nested { + min-height: 0; + } + + .card-skills { + position: relative; + } + .labels { + line-height: 2; + } + .space-top { + margin-top: 10px; + } + .label { + display: inline; + padding: 0.2em 0.6em 0.3em; + font-size: 75%; + font-weight: 600; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25em; + } + .label-keyword { + display: inline-block; + font-size: 0.9em; + padding: 5px; + border: 1px solid #357ebd; + margin-right: 5px; + } + .label-keyword p { + margin: 0; + } + .section-separated { + display: flex; + } +} diff --git a/packages/i18n/src/translations/curriculum-vitae.fr-FR.legacy.jsonc b/packages/i18n/src/translations/curriculum-vitae.fr-FR.legacy.jsonc new file mode 100644 index 0000000..276e10e --- /dev/null +++ b/packages/i18n/src/translations/curriculum-vitae.fr-FR.legacy.jsonc @@ -0,0 +1,181 @@ +{ + "$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json", + "basics": { + "name": "Théo LUDWIG", + "label": "Développeur Full Stack • Étudiant", + "image": "https://theoludwig.fr/images/logo_background.png", + "email": "contact@theoludwig.fr", + "age": "31/03/2003", + "location": { + "address": "Alsace, France", + }, + "url": "https://theoludwig.fr", + "summary": "Je me demande constamment comment améliorer notre présent, afin de rendre notre futur meilleur, particulièrement grâce aux progrès de l'informatique.
Ma priorité réside dans la création d'expériences utilisateurs (UX) intuitives, répondant aux besoins des utilisateurs de la manière la plus efficace que possible.", + }, + "education": [ + { + "startDate": "2023", + "endDate": "2024", + "studyType": "Bachelor Universitaire de Technologie (BUT) Informatique", + "institution": "IUT Robert Schuman à Illkirch-Graffenstaden", + "score": "3ème année", + "courses": [ + "Développement Web en Node.js et React.js", + "Intégration/Déploiement Continue et Docker", + "Complexité Algorithmique Théorique et Pratique en C++", + // "Projet développement LLM (Large Language Model) et NLP (Natural Language Processing)", + "Base de données NoSQL (Redis, MongoDB, Cassandra)", + ], + }, + { + "startDate": "2022", + "endDate": "2023", + "studyType": "Bachelor Universitaire de Technologie (BUT) Informatique", + "institution": "IUT Robert Schuman à Illkirch-Graffenstaden", + "score": "2ème année", + "courses": [ + "Développement Web avec le framework Laravel en PHP", + "Qualité de développement et Tests automatisés", + "Patrons et Principes de conceptions (Code maintenable et réutilisable) en UML", + "Programmation systèmes en C (Multi-Thread, Serveur/Client UDP/TCP)", + "Sécurisation des accès à la base de données et PL/SQL", + ], + }, + { + "startDate": "2021", + "endDate": "2022", + "studyType": "Bachelor Universitaire de Technologie (BUT) Informatique", + "institution": "IUT Robert Schuman à Illkirch-Graffenstaden", + "score": "1ère année", + "courses": [ + "Développement Orientée Objet en Java", + "Programmation systèmes en C (Allocation mémoire, Pointeurs, Structures)", + "Développement d'application Windows Forms (.NET Framework) en C#", + "Base de données relationnelles et langage SQL", + ], + }, + { + "startDate": "2019", + "endDate": "2021", + "studyType": "Baccalauréat Général (Mathématiques et Numériques Sciences Informatiques)", + "institution": "Lycée Heinrich Nessel à Haguenau", + "score": "Mention Assez Bien", + }, + // { + // "startDate": "2014", + // "endDate": "2018", + // "studyType": "Diplôme national du brevet", + // "institution": "Collège Gustave Doré à Hochfelden", + // "score": "Mention Bien" + // } + ], + "work": [ + { + "summary": "Développement de WebSurg, une université virtuelle consacrée à la formation médico-chirurgicale, en React.js/Next.js et API Platform avec Symfony.", + "website": "https://ircad.fr/", + "name": "IRCAD", + "location": "1 Place de l'Hôpital, 67000 Strasbourg", + "position": "Alternant Développeur Web Full Stack", + "startDate": "2023-08-28", + "endDate": "2024-09-02", + "duration": "1 an", + }, + { + "summary": "Développement d'un outil GED (Gestion Électronique de Documents) en React.js, Laravel et GraphQL.", + "website": "https://numerize.com/", + "name": "Numerize", + "location": "4 Rue Sophie Germain, 67720 Hœrdt", + "position": "Stagiaire Développeur Web Full Stack", + "startDate": "2023-04-11", + "endDate": "2023-07-26", + "duration": "4 mois", + }, + // { + // "summary": "Agent administratif - Numérisation et archivage des plans électriques initialement sous format papier calque.", + // "website": "https://www.es.fr/", + // "name": "ÉS (Électricité de Strasbourg)", + // "location": "5 Rue André Marie Ampère, 67450 Mundolsheim", + // "position": "Emploi d'été en qualité d'agent administratif", + // "startDate": "2021-07-07", + // "endDate": "2021-07-30", + // "duration": "1 mois" + // }, + { + "summary": "Développement d'un site web pour trouver un restaurant à la pause repas.", + "website": "https://itpartners.fr/", + "name": "Tribe | IT Partners", + "location": "16 Rue du Parc, 67205 Oberhausbergen", + "position": "Stage initiation métier développeur web", + "startDate": "2019-06-17", + "endDate": "2019-06-21", + "duration": "1 semaine", + }, + { + "description": "interests", + "summary": "Développement site web en React.js et Strapi.
Classé n°1 en France sur le Défi de l'entreprise ToolPad.", + "website": "https://nuitdelinfo.com/", + "name": "La Nuit de l'info 2021", + "position": "Participation en équipe de 5 personnes", + "startDate": "2021-12-02", + "endDate": "2021-12-03", + "duration": "1 semaine", + }, + { + "description": "interests", + "summary": "Hackathon développement d'une landing page et web scraping.", + "website": "https://wildcodeschool.fr/", + "name": "Wild Code School", + "location": "32 Rue du Bass. d'Austerlitz, 67100 Strasbourg", + "position": "Initiation métier Développeur web", + "startDate": "2019-06-24", + "endDate": "2019-06-28", + "duration": "1 semaine", + }, + // { + // "summary": "Apprentissage du métier \"Chargé de communication\" et des logiciels de graphisme tels que \"Adobe Photoshop\".", + // "website": "https://es.fr/", + // "name": "ÉS (Électricité de Strasbourg)", + // "location": "26 Bd du Président-Wilson, 67000 Strasbourg", + // "position": "Stage de découverte (3ème)", + // "startDate": "2018-02-19", + // "endDate": "2018-02-23", + // "duration": "1 semaine" + // } + ], + "interests": [ + { + "name": "Enthousiaste de l'Open-Source", + }, + { + "name": "Passionné de High-Tech", + }, + ], + "skills": [ + { + "keywords": ["JavaScript/TypeScript", "Python", "C/C++", "PHP"], + "name": "Langages de programmation", + }, + { + "keywords": ["HTML", "CSS", "Tailwind CSS", "React.js/Next.js"], + "name": "Frontend", + }, + { + "keywords": ["Laravel", "Node.js", "Fastify", "PostgreSQL"], + "name": "Backend", + }, + { + "keywords": [ + "GNU/Linux", + "Arch Linux", + "Visual Studio Code", + "Git", + "Docker", + ], + "name": "Logiciels et outils", + }, + { + "keywords": ["Permis B", "Anglais"], + "name": "Autres", + }, + ], +} diff --git a/packages/i18n/src/translations/en-US.json b/packages/i18n/src/translations/en-US.json index 1dbb33e..b01d658 100644 --- a/packages/i18n/src/translations/en-US.json +++ b/packages/i18n/src/translations/en-US.json @@ -7,6 +7,9 @@ "en-US": "English", "fr-FR": "French" }, + "common": { + "others": "Others" + }, "footer": { "all-rights-reserved": "All rights reserved" }, @@ -54,7 +57,8 @@ "programming-languages": "Programming languages", "frontend": "Frontend", "backend": "Backend", - "software-tools": "Software and tools" + "software-tools": "Software and tools", + "driving-license": "Permis B" }, "portfolio": { "title": "Portfolio", @@ -71,5 +75,110 @@ "title": "Open-Source", "description": "Most famous open source projects I contributed to." } + }, + "curriculum-vitae": { + "description": "Développeur Full Stack • Étudiant", + "about": { + "title": "À propos", + "description": "Je me demande constamment comment améliorer notre présent, afin de rendre notre futur meilleur, particulièrement grâce aux progrès de l'informatique.

Ma priorité réside dans la création d'expériences utilisateurs (UX) intuitives, répondant aux besoins des utilisateurs de la manière la plus efficace que possible." + }, + "education": { + "title": "Formations", + "iut": { + "study-type": "Bachelor Universitaire de Technologie (BUT) Informatique", + "institution": "IUT Robert Schuman à Illkirch-Graffenstaden", + "years": { + "2023-2024": { + "title": "2023 - 2024", + "description": "3ème année", + "courses": { + "web": "Développement Web en Node.js et React.js", + "ci-cd": "Intégration/Déploiement Continue et Docker", + "complexity-algorithms": "Complexité Algorithmique Théorique et Pratique en C++", + "no-sql": "Base de données NoSQL (Redis, MongoDB, Cassandra)" + } + }, + "2022-2023": { + "title": "2022 - 2023", + "description": "2ème année", + "courses": { + "web": "Développement Web avec le framework Laravel en PHP", + "tests": "Qualité de développement et Tests automatisés", + "clean-code": "Patrons et Principes de conceptions (Code maintenable et réutilisable) en UML", + "systems-c": "Programmation systèmes en C (Multi-Thread, Serveur/Client UDP/TCP)", + "sql-security": "Sécurisation des accès à la base de données et PL/SQL" + } + }, + "2021-2022": { + "title": "2021 - 2022", + "description": "1ère année", + "courses": { + "java": "Développement Orientée Objet en Java", + "systems-c": "Programmation systèmes en C (Allocation mémoire, Pointeurs, Structures)", + "windows-forms": "Développement d'application Windows Forms (.NET Framework) en C#", + "sql": "Base de données relationnelles et langage SQL" + } + } + } + }, + "lycee": { + "study-type": "Baccalauréat Général (Mathématiques et Numériques Sciences Informatiques)", + "institution": "Lycée Heinrich Nessel à Haguenau", + "score": "Mention Assez Bien", + "years": { + "2019-2021": { + "title": "2019 - 2021" + } + } + } + }, + "work": { + "title": "Expériences", + "ircad": { + "summary": "Développement de WebSurg, une université virtuelle consacrée à la formation médico-chirurgicale, en React.js/Next.js et API Platform avec Symfony.", + "website": "https://ircad.fr/", + "name": "IRCAD", + "location": "1 Place de l'Hôpital, 67000 Strasbourg", + "position": "Alternant Développeur Web Full Stack", + "startDate": "2023-08-28", + "endDate": "2024-09-02", + "duration": "1 an" + }, + "numerize": { + "summary": "Développement d'un outil GED (Gestion Électronique de Documents) en React.js, Laravel et GraphQL.", + "website": "https://numerize.com/", + "name": "Numerize", + "location": "4 Rue Sophie Germain, 67720 Hœrdt", + "position": "Stagiaire Développeur Web Full Stack", + "startDate": "2023-04-11", + "endDate": "2023-07-26", + "duration": "4 mois" + } + }, + "interests-work": { + "nuit-info-2021": { + "summary": "Développement site web en React.js et Strapi.

Classé n°1 en France sur le Défi de l'entreprise ToolPad.", + "website": "https://nuitdelinfo.com/", + "name": "La Nuit de l'info 2021", + "position": "Participation en équipe de 5 personnes", + "startDate": "2021-12-02", + "endDate": "2021-12-03", + "duration": "1 semaine" + }, + "wild-code-school": { + "summary": "Hackathon développement d'une landing page et web scraping.", + "website": "https://wildcodeschool.fr/", + "name": "Wild Code School", + "location": "32 Rue du Bassin d'Austerlitz, 67100 Strasbourg", + "position": "Initiation métier Développeur web", + "startDate": "2019-06-24", + "endDate": "2019-06-28", + "duration": "1 semaine" + } + }, + "interests": { + "open-source": "Enthousiaste de l'Open-Source", + "high-tech": "Passionné de High-Tech" + } } } diff --git a/packages/i18n/src/translations/fr-FR.json b/packages/i18n/src/translations/fr-FR.json index 0f7ae69..141bf28 100644 --- a/packages/i18n/src/translations/fr-FR.json +++ b/packages/i18n/src/translations/fr-FR.json @@ -7,6 +7,9 @@ "en-US": "Anglais", "fr-FR": "Français" }, + "common": { + "others": "Autres" + }, "footer": { "all-rights-reserved": "Tous droits réservés" }, @@ -54,7 +57,8 @@ "programming-languages": "Langages de programmation", "frontend": "Frontend", "backend": "Backend", - "software-tools": "Logiciels et outils" + "software-tools": "Logiciels et outils", + "driving-license": "Permis B" }, "portfolio": { "title": "Portfolio", @@ -71,5 +75,110 @@ "title": "Open-Source", "description": "Projets open source les plus célèbres auxquels j'ai contribué." } + }, + "curriculum-vitae": { + "description": "Développeur Full Stack • Étudiant", + "about": { + "title": "À propos", + "description": "Je me demande constamment comment améliorer notre présent, afin de rendre notre futur meilleur, particulièrement grâce aux progrès de l'informatique.

Ma priorité réside dans la création d'expériences utilisateurs (UX) intuitives, répondant aux besoins des utilisateurs de la manière la plus efficace que possible." + }, + "education": { + "title": "Formations", + "iut": { + "study-type": "Bachelor Universitaire de Technologie (BUT) Informatique", + "institution": "IUT Robert Schuman à Illkirch-Graffenstaden", + "years": { + "2023-2024": { + "title": "2023 - 2024", + "description": "3ème année", + "courses": { + "web": "Développement Web en Node.js et React.js", + "ci-cd": "Intégration/Déploiement Continue et Docker", + "complexity-algorithms": "Complexité Algorithmique Théorique et Pratique en C++", + "no-sql": "Base de données NoSQL (Redis, MongoDB, Cassandra)" + } + }, + "2022-2023": { + "title": "2022 - 2023", + "description": "2ème année", + "courses": { + "web": "Développement Web avec le framework Laravel en PHP", + "tests": "Qualité de développement et Tests automatisés", + "clean-code": "Patrons et Principes de conceptions (Code maintenable et réutilisable) en UML", + "systems-c": "Programmation systèmes en C (Multi-Thread, Serveur/Client UDP/TCP)", + "sql-security": "Sécurisation des accès à la base de données et PL/SQL" + } + }, + "2021-2022": { + "title": "2021 - 2022", + "description": "1ère année", + "courses": { + "java": "Développement Orientée Objet en Java", + "systems-c": "Programmation systèmes en C (Allocation mémoire, Pointeurs, Structures)", + "windows-forms": "Développement d'application Windows Forms (.NET Framework) en C#", + "sql": "Base de données relationnelles et langage SQL" + } + } + } + }, + "lycee": { + "study-type": "Baccalauréat Général (Mathématiques et Numériques Sciences Informatiques)", + "institution": "Lycée Heinrich Nessel à Haguenau", + "score": "Mention Assez Bien", + "years": { + "2019-2021": { + "title": "2019 - 2021" + } + } + } + }, + "work": { + "title": "Expériences", + "ircad": { + "summary": "Développement de WebSurg, une université virtuelle consacrée à la formation médico-chirurgicale, en React.js/Next.js et API Platform avec Symfony.", + "website": "https://ircad.fr/", + "name": "IRCAD", + "location": "1 Place de l'Hôpital, 67000 Strasbourg", + "position": "Alternant Développeur Web Full Stack", + "startDate": "2023-08-28", + "endDate": "2024-09-02", + "duration": "1 an" + }, + "numerize": { + "summary": "Développement d'un outil GED (Gestion Électronique de Documents) en React.js, Laravel et GraphQL.", + "website": "https://numerize.com/", + "name": "Numerize", + "location": "4 Rue Sophie Germain, 67720 Hœrdt", + "position": "Stagiaire Développeur Web Full Stack", + "startDate": "2023-04-11", + "endDate": "2023-07-26", + "duration": "4 mois" + } + }, + "interests-work": { + "nuit-info-2021": { + "summary": "Développement site web en React.js et Strapi.

Classé n°1 en France sur le Défi de l'entreprise ToolPad.", + "website": "https://nuitdelinfo.com/", + "name": "La Nuit de l'info 2021", + "position": "Participation en équipe de 5 personnes", + "startDate": "2021-12-02", + "endDate": "2021-12-03", + "duration": "1 semaine" + }, + "wild-code-school": { + "summary": "Hackathon développement d'une landing page et web scraping.", + "website": "https://wildcodeschool.fr/", + "name": "Wild Code School", + "location": "32 Rue du Bassin d'Austerlitz, 67100 Strasbourg", + "position": "Initiation métier Développeur web", + "startDate": "2019-06-24", + "endDate": "2019-06-28", + "duration": "1 semaine" + } + }, + "interests": { + "open-source": "Enthousiaste de l'Open-Source", + "high-tech": "Passionné de High-Tech" + } } } diff --git a/packages/ui/package.json b/packages/ui/package.json index 8059687..7ef5457 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -4,6 +4,7 @@ "private": true, "type": "module", "exports": { + "./CurriculumVitae": "./src/CurriculumVitae/CurriculumVitae.tsx", "./Design/Button": "./src/Design/Button/Button.tsx", "./Design/Link": "./src/Design/Link/Link.tsx", "./Design/Spinner": "./src/Design/Spinner/Spinner.tsx", diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitae.stories.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitae.stories.tsx new file mode 100644 index 0000000..1376965 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitae.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from "@storybook/react" + +import { CurriculumVitae as CurriculumVitaeComponent } from "./CurriculumVitae" + +const meta = { + title: "Curriculum Vitae/CurriculumVitae", + component: CurriculumVitaeComponent, +} satisfies Meta + +export default meta + +type Story = StoryObj + +export const CurriculumVitae: Story = { + args: {}, +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitae.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitae.tsx new file mode 100644 index 0000000..589a215 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitae.tsx @@ -0,0 +1,40 @@ +import { CurriculumVitaeAbout } from "./CurriculumVitaeAbout" +import { CurriculumVitaeEducation } from "./CurriculumVitaeEducation" +import { CurriculumVitaeInterests } from "./CurriculumVitaeInterests" +import { CurriculumVitaeProfile } from "./CurriculumVitaeProfile" +import { CurriculumVitaeSkills } from "./CurriculumVitaeSkills" +import { CurriculumVitaeWork } from "./CurriculumVitaeWork" + +export interface CurriculumVitaeProps {} + +export const CurriculumVitae: React.FC = () => { + return ( +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+
+
+
+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeAbout.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeAbout.tsx new file mode 100644 index 0000000..56a8ed8 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeAbout.tsx @@ -0,0 +1,19 @@ +import { useTranslations } from "next-intl" +import { FaUser } from "react-icons/fa" +import { CurriculumVitaeSection } from "./CurriculumVitaeSection" + +export interface CurriculumVitaeAboutProps {} + +export const CurriculumVitaeAbout: React.FC = () => { + const t = useTranslations() + + return ( + } + > +

{t.rich("curriculum-vitae.about.description")}

+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeEducation.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeEducation.tsx new file mode 100644 index 0000000..7421222 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeEducation.tsx @@ -0,0 +1,21 @@ +import { useTranslations } from "next-intl" +import { FaGraduationCap } from "react-icons/fa" +import { CurriculumVitaeSection } from "./CurriculumVitaeSection" + +export interface CurriculumVitaeEducationProps {} + +export const CurriculumVitaeEducation: React.FC< + CurriculumVitaeEducationProps +> = () => { + const t = useTranslations() + + return ( + } + > +

Test

+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeInterests.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeInterests.tsx new file mode 100644 index 0000000..a625364 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeInterests.tsx @@ -0,0 +1,21 @@ +import { useTranslations } from "next-intl" +import { FaHeart } from "react-icons/fa" +import { CurriculumVitaeSection } from "./CurriculumVitaeSection" + +export interface CurriculumVitaeInterestsProps {} + +export const CurriculumVitaeInterests: React.FC< + CurriculumVitaeInterestsProps +> = () => { + const t = useTranslations() + + return ( + } + > +

Test

+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeProfile.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeProfile.tsx new file mode 100644 index 0000000..85185bd --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeProfile.tsx @@ -0,0 +1,55 @@ +import { Link } from "@repo/i18n/navigation" +import { useTranslations } from "next-intl" +import Image from "next/image" +import { BirthDate } from "../Home/About/AboutList/BirthDate" + +export interface CurriculumVitaeProfileProps {} + +export const CurriculumVitaeProfile: React.FC< + CurriculumVitaeProfileProps +> = () => { + const t = useTranslations() + + return ( +
+
+
+ {t("meta.title")} +
+
+

+ {t("meta.title")} +

+
{t("curriculum-vitae.description")}
+
+ +
+
{t("home.about.nationality.value")}
+
+
+
+ +
+ + + https://theoludwig.fr/ + + +
+
+
+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeSection.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeSection.tsx new file mode 100644 index 0000000..3b8ddc2 --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeSection.tsx @@ -0,0 +1,23 @@ +export interface CurriculumVitaeSectionProps extends React.PropsWithChildren { + id: string + icon: React.ReactNode + title: string +} + +export const CurriculumVitaeSection: React.FC = ( + props, +) => { + const { id, icon, title, children } = props + + return ( +
+
{icon}
+ +
+

{title}

+ +
{children}
+
+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeSkills.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeSkills.tsx new file mode 100644 index 0000000..baacd2b --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeSkills.tsx @@ -0,0 +1,21 @@ +import { useTranslations } from "next-intl" +import { FaToolbox } from "react-icons/fa" +import { CurriculumVitaeSection } from "./CurriculumVitaeSection" + +export interface CurriculumVitaeSkillsProps {} + +export const CurriculumVitaeSkills: React.FC< + CurriculumVitaeSkillsProps +> = () => { + const t = useTranslations() + + return ( + } + > +

Test

+
+ ) +} diff --git a/packages/ui/src/CurriculumVitae/CurriculumVitaeWork.tsx b/packages/ui/src/CurriculumVitae/CurriculumVitaeWork.tsx new file mode 100644 index 0000000..55368ff --- /dev/null +++ b/packages/ui/src/CurriculumVitae/CurriculumVitaeWork.tsx @@ -0,0 +1,19 @@ +import { useTranslations } from "next-intl" +import { MdWork } from "react-icons/md" +import { CurriculumVitaeSection } from "./CurriculumVitaeSection" + +export interface CurriculumVitaeWorkProps {} + +export const CurriculumVitaeWork: React.FC = () => { + const t = useTranslations() + + return ( + } + > +

Test

+
+ ) +} diff --git a/packages/ui/src/Design/Button/Button.stories.tsx b/packages/ui/src/Design/Button/Button.stories.tsx index f9585ce..4407374 100644 --- a/packages/ui/src/Design/Button/Button.stories.tsx +++ b/packages/ui/src/Design/Button/Button.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react" import { expect, fn, userEvent, within } from "@storybook/test" -import { FaCheck } from "react-icons/fa6" +import { FaCheck } from "react-icons/fa" import type { ButtonLinkProps } from "./Button" import { Button } from "./Button" diff --git a/packages/ui/src/Home/About/AboutList/AboutItem.tsx b/packages/ui/src/Home/About/AboutList/AboutItem.tsx index a729769..3e5dbb7 100644 --- a/packages/ui/src/Home/About/AboutList/AboutItem.tsx +++ b/packages/ui/src/Home/About/AboutList/AboutItem.tsx @@ -1,6 +1,6 @@ export interface AboutItemProps { label: string - value: string + value: React.ReactNode link?: string } diff --git a/packages/ui/src/Home/About/AboutList/AboutItemBirthDate.tsx b/packages/ui/src/Home/About/AboutList/AboutItemBirthDate.tsx deleted file mode 100644 index b926f6b..0000000 --- a/packages/ui/src/Home/About/AboutList/AboutItemBirthDate.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client" - -import { BIRTH_DATE } from "@repo/utils/constants" -import { getAge, getISODate } from "@repo/utils/dates" -import { useTranslations } from "next-intl" -import { useMemo } from "react" -import { AboutItem } from "./AboutItem" - -export interface AboutItemBirthDateProps {} - -export const AboutItemBirthDate: React.FC = () => { - const t = useTranslations() - - const age = useMemo(() => { - return getAge(BIRTH_DATE) - }, []) - - return ( - - ) -} diff --git a/packages/ui/src/Home/About/AboutList/AboutList.tsx b/packages/ui/src/Home/About/AboutList/AboutList.tsx index e10818b..c539092 100644 --- a/packages/ui/src/Home/About/AboutList/AboutList.tsx +++ b/packages/ui/src/Home/About/AboutList/AboutList.tsx @@ -1,6 +1,6 @@ import { useTranslations } from "next-intl" import { AboutItem } from "./AboutItem" -import { AboutItemBirthDate } from "./AboutItemBirthDate" +import { BirthDate } from "./BirthDate" export interface AboutListProps {} @@ -13,7 +13,10 @@ export const AboutList: React.FC = () => { label={t("home.about.pronouns.label")} value={t("home.about.pronouns.value")} /> - + } + /> = () => { + const t = useTranslations() + + const age = useMemo(() => { + return getAge(BIRTH_DATE) + }, []) + + return t("home.about.birth-date.value", { + age, + birthDate: BIRTH_DATE_STRING, + }) +}