{p.resume}
-
- {benevolat.map((b) => (
-
-
-
- --- - ))} - + + ))} + + ) } diff --git a/src/components/sections/Certifications.astro b/src/components/sections/Certifications.astro index 0b6291e..b109d73 100644 --- a/src/components/sections/Certifications.astro +++ b/src/components/sections/Certifications.astro @@ -1,18 +1,22 @@ --- // Licences et certifications : une tuile par certification. -import { getCollection } from 'astro:content'; import SectionHead from '../SectionHead.astro'; +import Repli from '../Repli.astro'; import OrgMark from '../OrgMark.astro'; import Tags from '../Tags.astro'; import Icon from '../Icon.astro'; import { dateLisible, ordre, plusRecentsDabord } from '../../lib/dates'; -import { t } from '../../lib/reglages'; +import { reglages } from '../../lib/reglages'; +import { liste } from '../../lib/contenu'; +import { langueDe } from '../../lib/i18n'; interface Props { titre: string; } const { titre } = Astro.props; -const certifications = plusRecentsDabord((await getCollection('certifications')).map((e) => e.data), (c) => c.obtention); +const langue = langueDe(Astro.url); +const { t } = reglages(langue); +const certifications = plusRecentsDabord(await liste('certifications', langue), (c) => c.obtention); const aujourdhui = new Date().toISOString().slice(0, 7); --- @@ -20,31 +24,33 @@ const aujourdhui = new Date().toISOString().slice(0, 7); certifications.length > 0 && ({b.role}
- {periode(b.debut, b.fin)} ++ -
+ {benevolat.map((b) => (
+
-
+
+ +-++{b.role}
+ {periode(b.debut, b.fin, langue)} +{b.organisation}
+ + {b.description &&} {b.organisation}
- - {b.description &&} -
- -
- {certifications.map((c) => (
-
-
-
- ---{c.nom}
- {dateLisible(c.obtention)} -{c.organisme}
- - {c.identifiant && } -- {c.url && ( - - {t.afficherCertification}+ + ))} + + ) } diff --git a/src/components/sections/Experience.astro b/src/components/sections/Experience.astro index b7ed458..0d711ea 100644 --- a/src/components/sections/Experience.astro +++ b/src/components/sections/Experience.astro @@ -1,22 +1,25 @@ --- // Expérience : une tuile par entreprise ; plusieurs postes dans la même entreprise forment une frise. -import { getCollection } from 'astro:content'; import SectionHead from '../SectionHead.astro'; +import Repli from '../Repli.astro'; import Description from '../Description.astro'; import OrgMark from '../OrgMark.astro'; import Duree from '../Duree.astro'; import Tags from '../Tags.astro'; import { periode, plusRecentsDabord } from '../../lib/dates'; +import { liste } from '../../lib/contenu'; +import { langueDe } from '../../lib/i18n'; interface Props { titre: string; } const { titre } = Astro.props; +const langue = langueDe(Astro.url); const experiences = plusRecentsDabord( - (await getCollection('experiences')).map((e) => ({ - ...e.data, - postes: plusRecentsDabord(e.data.postes, (p) => p.debut), + (await liste('experiences', langue)).map((e) => ({ + ...e, + postes: plusRecentsDabord(e.postes, (p) => p.debut), })), (e) => e.postes[0].debut, ); @@ -27,59 +30,61 @@ const lieu = (p: { lieu?: string; mode?: string }) => [p.lieu, p.mode].filter(Bo experiences.length > 0 && (+ + -
+ {certifications.map((c) => (
+
-
+
+ +-+- )} -{c.nom}
+ {dateLisible(c.obtention, langue)}
- ))}
-
{c.organisme}
+ + {c.identifiant && } ++ {c.url && ( + + )} + - -
- {experiences.map((e) => {
- const p0 = e.postes[0];
- const debut = e.postes.at(-1)!.debut;
- const fin = e.postes.some((p) => p.fin === null) ? null : plusRecentsDabord(e.postes, (p) => p.fin)[0].fin;
- return (
-
-
-
- {e.postes.length === 1 ? ( - --- ) : ( -{p0.titre}
- {periode(p0.debut, p0.fin)} ++ -
+ {experiences.map((e) => {
+ const p0 = e.postes[0];
+ const debut = e.postes.at(-1)!.debut;
+ const fin = e.postes.some((p) => p.fin === null) ? null : plusRecentsDabord(e.postes, (p) => p.fin)[0].fin;
+ return (
+
-
+
+ {e.postes.length === 1 ? ( + +-++{p0.titre}
+ {periode(p0.debut, p0.fin, langue)} +{[e.entreprise, p0.contrat].filter(Boolean).join(' · ')}
+ + {p0.description &&} + {[e.entreprise, p0.contrat].filter(Boolean).join(' · ')}
- - {p0.description &&} - -
---{e.entreprise}
-- -
- {e.postes.map((p) => (
-
-
- -+ )} +-- )} - - ); - })} - + + ))} + +
{p.titre}
- {periode(p.debut, p.fin)} + ) : ( ++- - ))} - -++{e.entreprise}
++ -
+ {e.postes.map((p) => (
+
-
+ +- - {p.description &&++ + {p.description &&
{p.titre}
+ {periode(p.debut, p.fin, langue)} +} + } - -
+ );
+ })}
+ -
+
- -
- {formations.map((f) => (
-
-
-
- --- - ))} - + + ))} + + ) } diff --git a/src/components/sections/Projets.astro b/src/components/sections/Projets.astro index 95c9cad..185e76e 100644 --- a/src/components/sections/Projets.astro +++ b/src/components/sections/Projets.astro @@ -2,6 +2,7 @@ // Projets : une tuile par projet, en grille sur grand écran. import { getCollection } from 'astro:content'; import SectionHead from '../SectionHead.astro'; +import Repli from '../Repli.astro'; import ProjetCard from '../ProjetCard.astro'; import { trierProjets } from '../../lib/projets'; @@ -16,13 +17,15 @@ const projets = trierProjets(await getCollection('projets')); projets.length > 0 && ({f.etablissement}
- {(f.debut || f.fin) && {periode(f.debut, f.fin)}} ++ -
+ {formations.map((f) => (
+
-
+
+ +-++{f.etablissement}
+ {(f.debut || f.fin) && {periode(f.debut, f.fin, langue)}} +{[f.diplome, f.domaine].filter(Boolean).join(', ')}
+ {f.note && } + {f.activites && } + {f.description &&} + {[f.diplome, f.domaine].filter(Boolean).join(', ')}
- {f.note && } - {f.activites && } - {f.description &&} - -
) } diff --git a/src/data/benevolat.json b/src/data/benevolat.json index 6c9752b..06277d1 100644 --- a/src/data/benevolat.json +++ b/src/data/benevolat.json @@ -1,11 +1,102 @@ [ { - "id": "association-exemple", - "role": "Bénévole data", - "organisation": "Association Exemple", - "cause": "Environnement", - "debut": "2023-01", - "fin": null, - "description": "Nettoyage et structuration de données pour une ONG, puis tableau de bord de suivi d'impact." + "id": "mab-membre-actif", + "role": "Membre actif", + "organisation": "Miagistes Alumni Bordelais", + "logo": "logos/miagistesalumnibordelais.png", + "cause": "Arts et culture", + "debut": "2024-10", + "fin": "2026-09", + "description": "Association des Miagistes Alumni Bordelais depuis 2022\n• Création d'un large éventail de supports visuels pour l'association (publications et stories pour les réseaux sociaux, photos, brochures, modèles d'e-mails, PDF) sur plusieurs canaux (Facebook, Instagram, LinkedIn, Linktree)\n• Organisation et promotion d'afterworks de networking à Bordeaux, réunissant 30 à 60 participants par événement" + }, + { + "id": "mab-vp-communication", + "role": "Vice-président Communication", + "organisation": "Miagistes Alumni Bordelais", + "logo": "logos/miagistesalumnibordelais.png", + "cause": "Arts et culture", + "debut": "2022-10", + "fin": "2024-09", + "description": "Association des Miagistes Alumni Bordelais depuis 2022\n• Cofondation de l'association en 2022 pour renforcer la communauté des anciens de la MIAGE de Bordeaux\n• Conception de l'identité visuelle de l'association et élaboration de chartes graphiques annuelles et propres à chaque événement\n• Réalisation de plus de 150 supports de communication (publications et stories pour les réseaux sociaux, photos, brochures, modèles d'e-mails, PDF)\n• Visibilité en ligne accrue grâce à une croissance régulière de la communauté (+250 abonnés Instagram, +200 abonnés LinkedIn la première année)\n• Planification et mise en œuvre de stratégies de communication annuelles, avec des campagnes adaptées à chaque événement\n• Organisation et promotion de plus de 20 afterworks de networking à Bordeaux, réunissant 30 à 60 participants par événement" + }, + { + "id": "amb-membre-actif", + "role": "Membre actif", + "organisation": "AMB - Asso MIAGE Bordeaux", + "logo": "logos/assomiagebordeaux.png", + "cause": "Arts et culture", + "debut": "2022-06", + "fin": "2023-05", + "description": "Association des étudiants de la MIAGE de l'Université de Bordeaux depuis 1984\n• Participation à la préparation de divers événements étudiants\n• Contribution à l'organisation et à l'accompagnement sur place pendant les événements" + }, + { + "id": "amb-vice-president", + "role": "Vice-président", + "organisation": "AMB - Asso MIAGE Bordeaux", + "logo": "logos/assomiagebordeaux.png", + "cause": "Arts et culture", + "debut": "2021-06", + "fin": "2022-05", + "description": "Association des étudiants de la MIAGE de l'Université de Bordeaux depuis 1984\n• Contribution à l'organisation de grands événements étudiants, dont des afterworks (~170 participants), le week-end d'intégration (~100 participants) et le week-end ski (~110 participants)\n• Bénévole dans l'équipe d'organisation de la 12e édition du Gala MIAGE Bordeaux aux Bassins des Lumières (~400 participants)\n• Participation à la rédaction de documents de capitalisation pour aider les futurs bureaux à organiser les événements récurrents (soirée d'intégration, WEI, WES, etc.)" + }, + { + "id": "amb-president", + "role": "Président", + "organisation": "AMB - Asso MIAGE Bordeaux", + "logo": "logos/assomiagebordeaux.png", + "cause": "Arts et culture", + "debut": "2020-06", + "fin": "2021-05", + "description": "Association des étudiants de la MIAGE de l'Université de Bordeaux depuis 1984\n• Contribution à l'organisation de grands événements étudiants malgré la pandémie de COVID-19, dont des afterworks (~150 participants) et des rencontres en ligne sur Discord (~50 participants)\n• Maintien d'une forte cohésion entre les promotions MIAGE ainsi qu'avec les générations d'anciens\n• Engagement actif dans la vie étudiante locale et régionale au sein de la fédération territoriale ATENA (assemblées générales, votes, soutien aux initiatives)\n• Soutien à la promotion de la formation MIAGE, de ses traditions et de ses projets au sein de la fédération nationale MIAGE Connection (assemblées générales, votes, initiatives)" + }, + { + "id": "mayday-festival", + "role": "Staff bénévole", + "organisation": "Mayday Festival", + "logo": "logos/maydayfestival.png", + "cause": "Arts et culture", + "debut": "2021-10", + "fin": "2021-10", + "description": "Festival de musique créé en 2016 à Talence, organisé en association depuis 2018.\n• Surveillance et sécurisation du périmètre du festival pour garantir la sécurité des festivaliers\n• Accueil des festivaliers : réponse à leurs questions et orientation sur le site\n• Renfort au bar pendant les heures de pointe pour absorber une forte affluence" + }, + { + "id": "miage-connection-vp-reseau", + "role": "Vice-président Réseau", + "organisation": "MIAGE Connection", + "logo": "logos/miageconnection.png", + "cause": "Droits civiques et action sociale", + "debut": "2021-03", + "fin": "2021-10", + "description": "Fédération nationale des étudiants en MIAGE en France depuis 2005\n• Maintien du lien entre les associations membres (BDE, Junior-Entreprises, associations d'anciens) pendant la crise du Covid-19\n• Collecte et partage des activités des associations membres via la plateforme en ligne MIAGE Weather, favorisant la visibilité et l'échange d'idées et d'actualités sur les événements\n• Facilitation de la collaboration avec le pôle Formation pour accompagner les membres dans leur préparation académique\n• Accompagnement du renouvellement des bureaux étudiants pour assurer la continuité des activités essentielles à la MIAGE" + }, + { + "id": "miage-connection-vp-international", + "role": "Vice-président International", + "organisation": "MIAGE Connection", + "logo": "logos/miageconnection.png", + "cause": "Formation", + "debut": "2021-03", + "fin": "2021-10", + "description": "Fédération nationale des étudiants en MIAGE en France depuis 2005\n• Maintien du lien avec les communautés MIAGE et les réseaux équivalents à l'étranger (Luxembourg, Belgique, Canada, États-Unis, etc.)\n• Rédaction d'un guide d'accompagnement pour aider les étudiants à s'installer à l'étranger : démarches administratives, conseils pratiques, logement et recommandations recueillies auprès d'anciens déjà expatriés" + }, + { + "id": "ub-elu-etudiant", + "role": "Élu étudiant", + "organisation": "Université de Bordeaux", + "logo": "logos/universitedebordeaux.png", + "cause": "Droits civiques et action sociale", + "debut": "2020-12", + "fin": "2022-08", + "description": "• Représentation des étudiants dans les conseils centraux de l'université (notamment le Conseil d'administration et le Conseil académique), avec participation aux décisions pédagogiques, financières et administratives\n• Siège aux conseils de collège et de composante, avec contribution à la conception et à la validation de l'offre de formation, des modalités d'évaluation, des critères d'admission et de la politique de vie étudiante\n• Collaboration avec les vice-présidents de campus sur le bien-être étudiant, la vie de campus et la vie associative, en tant qu'intermédiaire entre les étudiants, l'administration et les associations étudiantes" + }, + { + "id": "abeii-tresorier", + "role": "Trésorier", + "organisation": "L'ABEII", + "logo": "logos/lassoif.png", + "cause": "Services sociaux", + "debut": "2018-04", + "fin": "2019-03", + "description": "Association bordelaise des étudiants en informatique de l'Université de Bordeaux depuis 2012\n• Planification et coordination d'événements étudiants de 50 à plus de 150 participants, avec des budgets allant jusqu'à 3 000 €\n• Supervision du fonctionnement quotidien du foyer étudiant, fréquenté par plus de 200 étudiants\n• Gestion des stocks, des prix et des ventes de snacks et de boissons pour assurer des recettes régulières\n• Élaboration et suivi des budgets pour garantir la pérennité financière de l'association" } ] diff --git a/src/data/en/benevolat.json b/src/data/en/benevolat.json new file mode 100644 index 0000000..15ac13a --- /dev/null +++ b/src/data/en/benevolat.json @@ -0,0 +1,62 @@ +[ + { + "id": "mab-membre-actif", + "role": "Active Member", + "cause": "Arts and Culture", + "description": "Association of Miagistes Alumni Bordelais since 2022\n• Created a wide range of visual assets for the association (social media posts, stories, photos, brochures, email templates, PDFs) across multiple channels (Facebook, Instagram, LinkedIn, Linktree)\n• Organized and promoted networking Afterworks in Bordeaux, bringing together 30–60 participants per event" + }, + { + "id": "mab-vp-communication", + "role": "Vice President Communications", + "cause": "Arts and Culture", + "description": "Association of Miagistes Alumni Bordelais since 2022\n• Co-founded the association in 2022 to strengthen the Bordeaux MIAGE alumni community\n• Designed the association’s visual identity and developed annual and event-specific brand guidelines\n• Produced 150+ communication materials (social media posts, stories, photos, brochures, email templates, PDFs)\n• Increased online visibility with steady community growth (+250 Instagram followers, +200 LinkedIn followers in the first year)\n• Planned and executed annual communication strategies, with tailored campaigns for each event\n• Organized and promoted 20+ networking Afterworks in Bordeaux, bringing together 30–60 participants per event" + }, + { + "id": "amb-membre-actif", + "role": "Active Member", + "cause": "Arts and Culture", + "description": "Association of MIAGE Students at the University of Bordeaux since 1984\n• Assisted in the preparation of various student events\n• Contributed to on-site organization and support during events" + }, + { + "id": "amb-vice-president", + "role": "Vice President", + "cause": "Arts and Culture", + "description": "Association of MIAGE Students at the University of Bordeaux since 1984\n• Contributed to the organization of major student events, including Afterworks (~170 participants), Integration Weekend (~100 participants), and Ski Weekend (~110 participants)\n• Volunteered as a staff member for the 12th edition of the MIAGE Bordeaux Gala at the Bassins des Lumières (~400 participants)\n• Assisted in drafting capitalization documents to support future student boards in organizing recurring events (Integration Night, WEI, WES, etc.)" + }, + { + "id": "amb-president", + "role": "President", + "cause": "Arts and Culture", + "description": "Association of MIAGE Students at the University of Bordeaux since 1984\n• Contributed to the organization of major student events despite the COVID-19 pandemic, including Afterworks (~150 participants) and online Discord gatherings (~50 participants)\n• Helped maintain strong cohesion across MIAGE cohorts as well as with alumni generations\n• Actively engaged in local and regional student life through the territorial federation ATENA (general assemblies, voting, and support of initiatives)\n• Supported the promotion of the MIAGE program, its traditions, and projects through the national federation MIAGE Connection (general assemblies, voting, and initiatives)" + }, + { + "id": "mayday-festival", + "role": "Volunteer Staff", + "cause": "Arts and Culture", + "description": "Music festival created in 2016 in Talence (FR), organized as an association since 2018.\n• Monitored and secured the festival perimeter to ensure attendee safety\n• Assisted festivalgoers by answering questions and providing on-site guidance\n• Supported bar service during peak hours to manage high-volume demand" + }, + { + "id": "miage-connection-vp-reseau", + "role": "Vice President Network", + "cause": "Civil Rights and Social Action", + "description": "National Federation of MIAGE Students in France since 2005\n• Maintained connections between member organizations (student unions, junior enterprises, alumni groups) during the Covid-19 crisis\n• Collected and shared activities from member associations through the online MIAGE Weather platform, enabling visibility and exchange of event ideas and updates\n• Facilitated collaboration with the Training Division to support members’ academic preparation\n• Assisted in the renewal of student boards to ensure continuity of activities essential to the MIAGE program" + }, + { + "id": "miage-connection-vp-international", + "role": "Vice President International", + "cause": "Education", + "description": "National Federation of MIAGE Students in France since 2005\n• Maintained connections with MIAGE communities and equivalent networks abroad (Luxembourg, Belgium, Canada, United States, etc.)\n• Authored a support guide to help students settle abroad, covering legal procedures, practical advice, housing tips, and recommendations collected from alumni already living overseas" + }, + { + "id": "ub-elu-etudiant", + "role": "Student Elected Representative", + "cause": "Civil Rights and Social Action", + "description": "• Represented the student body in central university bodies (such as the Board of Administration and the Academic Council), participating in decision-making on academic, financial, and administrative matters\n• Served on Faculty/Component Councils, contributing to the design and validation of course offerings, evaluation methods, admission criteria, and student life policy\n• Collaborated with Vice-Presidents of Campus to address student welfare, campus life, and associative activities, acting as a liaison between students, administration, and student associations" + }, + { + "id": "abeii-tresorier", + "role": "Treasurer", + "cause": "Social Services", + "description": "Bordeaux Association of IT Students at the University of Bordeaux since 2012\n• Planned and coordinated student events for 50–150+ participants, managing budgets of up to €3K\n• Oversaw daily operations of the student common room serving 200+ students\n• Managed inventory, pricing, and snack/drink sales to ensure consistent revenue flow\n• Created and monitored budgets to secure the association’s financial sustainability" + } +] diff --git a/src/data/en/experiences.json b/src/data/en/experiences.json new file mode 100644 index 0000000..ccbcc04 --- /dev/null +++ b/src/data/en/experiences.json @@ -0,0 +1,76 @@ +[ + { + "id": "betclic-group", + "postes": [ + { + "contrat": "Full-time", + "mode": "Hybrid", + "description": "Data Engineer in a Data team working across sports betting, casino, poker and horse racing.\n\nI work on data modeling, building transformations with dbt and SQL, and delivering data products and dashboards to business teams. I also contribute to the continuous improvement of the Data platform, to reducing technical debt and to getting ready for the challenges of major international sporting events.\nI also use generative AI tools to speed up development, analysis and the use of data.", + "competences": [ + "SQL", + "dbt", + "Snowflake", + "Tableau", + "Omni", + "Generative AI (ChatGPT, Claude, Codex, Cortex, Rovo)" + ] + } + ] + }, + { + "id": "thelio", + "postes": [ + { + "contrat": "Full-time", + "mode": "Hybrid", + "description": "Contributed to several strategic Data Engineering and Data Analytics projects for two leading international groups:\n\nClient – Global leader in animal health\n• Designed dashboards (Salesforce Analytics Studio, Power BI) for sales tracking and data quality: far fewer manual checks and faster response from the teams.\n• Developed audit management solutions in 50+ countries, with automatic translation into 30+ languages and advanced security (RLS).\n• Synchronized and standardized multi-source sales data for 20+ subsidiaries, ensuring a consistent international CRM rollout.\n• Automated and standardized KPIs with Databricks (medallion architecture), cutting manual extractions and saving business teams dozens of hours per month.\n\nClient – Technology leader for the fashion industry:\n• Redesigned a contract management model with incremental pipelines (delta logic, medallion architecture), reducing processing times over time and making the data more reliable.\n• Set up centralized Power BI reporting (star schema, DAX), adopted by operational teams, replacing fragmented Excel files and halving manual reporting effort.\n\nOverall impact: more reliable and available data, lower maintenance costs, faster decision-making (from several days to a few hours), and wider adoption of BI solutions by business teams.\n\nCompany life: actively involved in the company's culture by organizing events and collective initiatives." + }, + { + "contrat": "Apprenticeship", + "description": "Contributed to several strategic projects to modernize and secure data flows for leading organizations in the public sector and tourism.\n\nClient – Major French local authority\n• Set up a unified synchronization framework between two Data Warehouses, improving data consistency and the reliability of BI analyses. Designed scalable flows (Talend, SQL, Oracle) that anticipate structural changes to ensure long-term scalability.\n\nClient – Leading residential tourism group in France\n• Brought in-house and industrialized Talend ETL pipelines, replacing legacy PHP flows, for better control and simpler maintenance.\n\nOverall impact: more reliable and consistent data, lower operating costs, and BI and business teams able to make use of their data faster.\n\nCompany life: actively involved in the company's culture by organizing events and collective initiatives.", + "competences": [ + "Data Engineering", + "Extract, Transform, Load (ETL)" + ] + } + ] + }, + { + "id": "legalyspace", + "postes": [ + { + "titre": "Full Stack Web Developer", + "contrat": "Apprenticeship", + "mode": "On-site", + "description": "Contributed to several strategic full stack development projects for a fast-growing legaltech company in Bordeaux.\n\n• Designed and implemented key features (Java EE, PL/SQL, HTML5, CSS, JavaScript), including a customer tracking page, an internal dashboard and the integration of third-party services (Tradeshift), improving both security and productivity.\n• Built a Java library generating XML files compliant with the UBL 2.1 standard (JAXB), documented and versioned on GitHub, automating the production of tax documents and easing their integration into invoicing systems.\n\nOverall impact: a better customer experience, streamlined internal processes and stronger compliance with international standards, supporting the platform's growth and reliability.", + "competences": [ + "SQL", + "User Interface Design" + ] + } + ] + }, + { + "id": "sopra-steria", + "postes": [ + { + "titre": "Web Application Developer", + "contrat": "Internship", + "mode": "On-site", + "description": "Contributed to a strategic project centralizing accounting tools for a major public body.\n\n• Developed a web application (Java EE, SQL, HTML5, CSS, JavaScript) with new features, including “Organizations” management and session saving, contributing to a unified tool for affiliated practitioners nationwide.\n\nOverall impact: a faster and more reliable monthly closing of accounts thanks to a centralized, high-performance tool." + } + ] + }, + { + "id": "millesima", + "postes": [ + { + "titre": "Web Application Developer", + "contrat": "Internship", + "lieu": "Bordeaux Area, France", + "mode": "On-site", + "description": "Contributed to a strategic full stack development project for an international fine wine event.\n\n• Designed and deployed an interactive web application (Java EE, HTML5, CSS, JavaScript) with a registration form, 360° animations, an admin area, a JSON REST API and GDPR-compliant security, used on touch kiosks and iPads by several hundred attendees at the 2019 Bordeaux Grands Crus Weekend.\n\nOverall impact: a stable, secure and engaging experience that made the client's booth more attractive and boosted brand visibility at a major international event." + } + ] + } +] diff --git a/src/data/en/formations.json b/src/data/en/formations.json new file mode 100644 index 0000000..3c82ea8 --- /dev/null +++ b/src/data/en/formations.json @@ -0,0 +1,36 @@ +[ + { + "id": "master-miage", + "diplome": "Master's degree", + "note": "Grade: Graduated", + "activites": "Student union (Asso MIAGE Bordeaux): President (1 year) then Vice President (1 year); College Council (Peixotto & Bordes campuses): Student elected representative (1 year 9 months).", + "description": "The MIAGE master's degree (Computer Methods Applied to Business Management) trains business executives who are experts in information systems engineering and management.\nThis five-year program combines a dual skill set in digital sciences (programming, mathematical logic…) and management sciences (finance, accounting, marketing, project management…)." + }, + { + "id": "licence-miage", + "diplome": "Bachelor's degree (3rd year), MIAGE track", + "domaine": "Computer Science", + "note": "Grade: Graduated", + "description": "The third year of the bachelor's MIAGE track (Computer Methods Applied to Business Management) combines a dual skill set in digital sciences (programming, mathematical logic…) and management sciences (finance, accounting, marketing, project management…).\nThis three-year program is required to enter a MIAGE master's degree." + }, + { + "id": "dut-info", + "diplome": "DUT (two-year technical degree)", + "note": "Grade: Graduated", + "activites": "Student union (L'ABEII): Treasurer (1 year)", + "description": "The DUT in Computer Science trains general-purpose computer scientists through solid theoretical and practical training." + }, + { + "id": "licence-maths", + "diplome": "Bachelor's degree", + "note": "Grade: First year completed.", + "description": "The bachelor's degree in mathematics gives students solid knowledge of mathematics, covering the basics of algebra, geometry, analysis and probability." + }, + { + "id": "bac-s", + "diplome": "Baccalauréat (high school diploma)", + "domaine": "Science", + "note": "Grade: Graduated", + "description": "Mathematics option." + } +] diff --git a/src/data/en/profil.json b/src/data/en/profil.json new file mode 100644 index 0000000..8371a9a --- /dev/null +++ b/src/data/en/profil.json @@ -0,0 +1,8 @@ +{ + "langues": [ + { "nom": "French", "niveau": "Native" }, + { "nom": "English", "niveau": "Professional working proficiency" }, + { "nom": "Spanish", "niveau": "Elementary proficiency" } + ], + "aPropos": "At Betclic, I make data talk: modeling, dbt and SQL transformations, data products and dashboards for business teams, with a little help from generative AI. On the side, I code a lot for myself: an everyday need, a blocker that bugs me or just an idea worth trying, and it turns into a project. I like trying things, getting it wrong, finding the fix… and starting again." +} diff --git a/src/data/en/site.json b/src/data/en/site.json new file mode 100644 index 0000000..44e11c5 --- /dev/null +++ b/src/data/en/site.json @@ -0,0 +1,57 @@ +{ + "meta": { + "titre": "oreLINK · Aurélien Bertrand, Data Engineer", + "description": "Portfolio of Aurélien Bertrand (oreLINK), Data Engineer at Betclic Group in Bordeaux: experience, projects, education, certifications and volunteering." + }, + + "sections": [ + { "id": "experience", "titre": "Experience" }, + { "id": "projets", "titre": "Projects" }, + { "id": "formation", "titre": "Education" }, + { "id": "certifications", "titre": "Licenses & certifications" }, + { "id": "benevolat", "titre": "Volunteering" } + ], + + "textes": { + "meContacter": "Contact me", + "aPropos": "About", + "activites": "Activities and societies", + "voirPlus": "See more", + "voirMoins": "See less", + "toutAfficher": "Show all", + "delivreeEn": "Issued", + "expireEn": "Expires", + "expireeEn": "Expired", + "identifiant": "Credential ID", + "afficherCertification": "Show credential", + "commentJeLaiFait": "How I built it", + "commentJeLaiRealise": "How I built it", + "voirLeProjet": "View project", + "codeSource": "Source code", + "retour": "Back to portfolio", + "statut": "Status", + "commenceEn": "Started", + "role": "Role", + "technologies": "Technologies", + "sommaire": "Contents", + "precedent": "Previous", + "suivant": "Next", + "statuts": { + "en-ligne": "Live", + "en-cours": "In progress", + "archive": "Archived" + }, + "themeClair": "Switch to light theme", + "themeSombre": "Switch to dark theme", + "allerAuContenu": "Skip to content", + "codeDuSite": "Site source", + "introuvableTitre": "Page not found", + "introuvableTexte": "This page doesn't exist, or no longer does.", + "retourAccueil": "Back to home", + "chez": "at", + "competences": "Skills", + "liensExternes": "External links", + "autresProjets": "Other projects", + "changerDeLangue": "Change language" + } +} diff --git a/src/data/profil.json b/src/data/profil.json index 33e4437..2dce5b7 100644 --- a/src/data/profil.json +++ b/src/data/profil.json @@ -14,11 +14,16 @@ "ton": "none" }, "localisation": "Bordeaux, France", + "langues": [ + { "code": "fr", "nom": "Français", "niveau": "Langue natale" }, + { "code": "en", "nom": "Anglais", "niveau": "Capacité professionnelle" }, + { "code": "es", "nom": "Espagnol", "niveau": "Notions de base" } + ], "email": "orelienbertrand@gmail.com", "liens": { "linkedin": "https://www.linkedin.com/in/aurelienbertrand/", "github": "https://github.com/oreLINK", "cv": "" }, - "aPropos": "Data Engineer avec un pied côté Analytics Engineering : de la source brute jusqu'à des tables propres, testées et documentées. En dehors du travail, je construis des petits sites statiques autour de mes passions : la montagne, les transports, les langues." + "aPropos": "Chez Betclic, je fais parler la donnée : modélisation, transformations dbt et SQL, produits data et tableaux de bord pour les équipes métiers, avec un coup de main de l'IA générative. À côté, je code beaucoup pour moi : un besoin du quotidien, un blocage qui m'agace ou juste une idée à tester, et ça devient un projet. J'aime tenter des choses, me planter, trouver la solution… et recommencer." } diff --git a/src/data/site.json b/src/data/site.json index 3ac03ff..c69cb0d 100644 --- a/src/data/site.json +++ b/src/data/site.json @@ -20,16 +20,18 @@ { "id": "projets", "titre": "Projets", "afficher": false }, { "id": "formation", "titre": "Formation", "afficher": true }, { "id": "certifications", "titre": "Licences et certifications", "afficher": false }, - { "id": "benevolat", "titre": "Bénévolat", "afficher": false } + { "id": "benevolat", "titre": "Bénévolat", "afficher": true } ], + "hauteurSectionRepliee": 500, + "textes": { "meContacter": "Me contacter", "aPropos": "À propos", - "aujourdhui": "aujourd’hui", "activites": "Activités et associations", "voirPlus": "Voir plus", "voirMoins": "Voir moins", + "toutAfficher": "Tout afficher", "delivreeEn": "Délivrée en", "expireEn": "Expire en", "expireeEn": "Expirée en", @@ -58,7 +60,12 @@ "codeDuSite": "Code du site", "introuvableTitre": "Page introuvable", "introuvableTexte": "Cette page n'existe pas, ou plus.", - "retourAccueil": "Retour à l'accueil" + "retourAccueil": "Retour à l'accueil", + "chez": "chez", + "competences": "Compétences", + "liensExternes": "Liens externes", + "autresProjets": "Autres projets", + "changerDeLangue": "Changer de langue" }, "piedDePage": { diff --git a/src/data/themes.json b/src/data/themes.json new file mode 100644 index 0000000..7ae8468 --- /dev/null +++ b/src/data/themes.json @@ -0,0 +1,15 @@ +{ + "forcer": "", + + "themes": [ + { + "id": "halloween", + "nom": "Halloween", + "actif": true, + "debut": "10-01", + "fin": "10-31", + "accentClair": "#C2410C", + "accentSombre": "#FB923C" + } + ] +} diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index a59e233..6c33b7b 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -3,8 +3,11 @@ import '../styles/global.css'; import Icons from '../components/Icons.astro'; import Icon from '../components/Icon.astro'; import Brand from '../components/Brand.astro'; +import Drapeau from '../components/Drapeau.astro'; +import Halloween from '../components/habillages/Halloween.astro'; import { url, asset } from '../lib/paths'; -import { site, profil, t } from '../lib/reglages'; +import { reglages, themes } from '../lib/reglages'; +import { LANGUES, cheminSansLangue, langueDe, type Langue } from '../lib/i18n'; interface Props { title?: string; @@ -12,20 +15,28 @@ interface Props { /** Lien de retour affiché en haut à gauche (pages de projet). */ back?: { href: string; label: string }; } +const langue = langueDe(Astro.url); +const { site, profil, t } = reglages(langue); const { title = site.meta.titre, description = site.meta.description, back } = Astro.props; const canonical = new URL(Astro.url.pathname, Astro.site); +// La même page dans chaque langue (sélecteur de langue et liens hreflang). +const chemin = cheminSansLangue(Astro.url); +const versions = (Object.keys(LANGUES) as Langue[]).map((code) => ({ code, ...LANGUES[code], href: url(chemin, code) })); +// Thèmes d'habillage (src/data/themes.json, voir THEMES.md), choisis dans le navigateur d'après la date. +const habillages = { forcer: themes.forcer, themes: themes.themes.map(({ nom, ...t }) => t) }; const annee = new Date().getFullYear(); const accents = `--accent-light: ${site.couleurs.accentClair}; --accent-dark: ${site.couleurs.accentSombre};`; --- - +- -
- {projets.map((p) => (
-
-
-
-
- ))}
-
+ -
+ {projets.map((p) => (
+
-
+
+
+ ))}
+
{title} + {versions.map((v) => )} @@ -37,18 +48,51 @@ const accents = `--accent-light: ${site.couleurs.accentClair}; --accent-dark: ${ - {/* Avant le premier rendu : thème choisi, pour éviter un flash de la mauvaise couleur. */} + {/* Avant le premier rendu : thème choisi pendant la visite, pour éviter un flash de la mauvaise + couleur. Sans choix, le thème est celui du système (voir ui.ts). */} + + {/* Thème d'habillage du moment, posé avant le premier rendu. `?theme=` (ou `?theme=aucun`) + dans l'adresse permet de le prévisualiser à toute date. */} + {t.allerAuContenu} - + @@ -56,24 +100,42 @@ const accents = `--accent-light: ${site.couleurs.accentClair}; --accent-dark: ${ { back && ( ) } - + -
+
-
+
-
+
-
+