move all components that are exclusive to one page

This commit is contained in:
2026-04-23 15:37:39 +02:00
parent 23233d4be6
commit d34eb5714f
17 changed files with 19 additions and 19 deletions
@@ -0,0 +1,37 @@
#experiences-section {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
scroll-margin-top: 80px;
}
.experiences-container {
width: 100%;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.experiences-container::before {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 2px;
height: 100%;
background-color: rgba(176, 176, 176, 0.2);
}
@media (max-width: 768px) {
.experiences-container {
width: 90%;
align-items: flex-start;
margin-right: 20px;
}
.experiences-container::before {
left: 20px;
}
}
@@ -0,0 +1,49 @@
import './Experiences.css';
import SingleExperience from '../SingleExperience/SingleExperience.jsx';
import React, {useEffect, useState} from "react";
function Experiences() {
const [experiences, setExperiences] = useState([]);
const [experienceTasks, setExperienceTasks] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
const fetchExperiencesAndTasks = async () => {
try {
let response = await fetch('/api/experiences/');
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
let data = await response.json();
setExperiences(data.data);
response = await fetch('/api/experienceTasks/');
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
data = await response.json();
setExperienceTasks(data.data);
} catch (err) {
setError(err.message);
}
};
fetchExperiencesAndTasks();
}, []);
if (error) {
return <div>Error retrieving data: {error}</div>;
}
return (
<section id="experiences-section">
<h1 className="section-title">Experiences</h1>
<div className="experiences-container">
{experiences.map((exp) => (
<SingleExperience experience={exp} tasks={experienceTasks.filter(task => task.experience_id === exp.id)}/>
))}
</div>
</section>
);
}
export default Experiences;
+83
View File
@@ -0,0 +1,83 @@
#home-section {
position: relative;
min-height: 110vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
}
#home-section h1{
margin-bottom: 0;
margin-left: 40px;
margin-right: 40px;
}
#home-section h2 {
font-size: 1.8rem;
color: var(--title-color);
margin-bottom: 1rem;
}
#home-section p {
margin-bottom: 2rem;
color: var(--title-color);
max-width: 40%;
}
.highlight {
color: var(--important-color);
}
.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
background-color: var(--important-color);
color: white;
transition: background-color 0.3s ease;
margin-bottom: 200px;
}
.btn:hover {
background-color: #b94a36;
cursor: pointer;
}
@media (max-width: 840px) {
.btn {
margin-bottom: 10%;
}
#home-section p{
max-width: 60%;
}
}
@media (max-width: 656px) {
#home-section h1{
font-size: 3.5rem;
}
#home-section h2 {
font-size: 1.5rem;
}
}
@media (max-width: 584px) {
#home-section h1{
font-size: 3rem;
}
}
+22
View File
@@ -0,0 +1,22 @@
import './Home.css';
import Background from "../../../../components/thirdParty/Background/Background.jsx";
import NavBar from "../../../../components/NavBar/NavBar.jsx";
function Home() {
return (
<section id="home-section">
<Background />
<NavBar/>
<h1>Hello, I'm<span className="highlight"> Giovanni Josserand</span></h1>
<h2>Junior Developer</h2>
<p>
Passionate about development, I am currently looking
for an opportunity to put my skills into practice and continue learning.
</p>
<a href="/assets/documents/CV.pdf" target="_blank" className="btn">Download my CV</a>
</section>
);
}
export default Home;
@@ -0,0 +1,99 @@
.experience-card {
position: relative;
width: 100%;
margin-bottom: 3rem;
padding: 1.5rem;
display: flex;
gap: 6rem;
justify-content: center;
}
.experience-card::before {
content: '';
position: absolute;
top: 25px;
left: 50%;
transform: translateX(-50%);
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #D95F46;
border: 3px solid rgba(176, 176, 176, 0.2);
}
.experience-card-left {
width: 25%;
text-align: end;
}
.experience-card-right {
width: 25%;
}
.experience-company {
color: var(--important-color);
font-size: 1.5rem;
margin: 0;
}
.experience-role {
font-size: 1.5rem;
font-weight: bold;
color: var(--title-color);
margin: 0;
}
.experience-location,
.experience-duration {
font-size: 0.95rem;
color: var(--text-color);
margin: 0.25rem 0 0;
white-space: nowrap;
}
.experience-tasks {
list-style: none;
padding: 0;
margin-top: 1rem;
}
.experience-tasks li {
position: relative;
padding-left: 1.5rem;
margin-bottom: 0.5rem;
color: var(--text-color);
text-align: left;
}
.experience-tasks li::before {
content: '';
position: absolute;
left: 0;
top: 0;
color: var(--important-color);
font-weight: bold;
font-size: 1.2rem;
line-height: 1;
}
@media (max-width: 768px) {
.experience-card{
display: flex;
flex-direction: column;
gap: 0;
}
.experience-card::before {
left: 20px;
top: 31px;
}
.experience-card-left, .experience-card-right{
width: fit-content;
margin-left: 20px;
}
.experience-card-left{
text-align: left;
}
}
@@ -0,0 +1,22 @@
import './SingleExperience.css';
function SingleExperience({ experience, tasks }) {
return (
<div className="experience-card">
<div className="experience-card-left">
<h3 className="experience-company">{experience.company}</h3>
<p className="experience-location">{experience.location}</p>
<p className="experience-duration">{experience.duration}</p>
</div>
<div className="experience-card-right">
<h3 className="experience-role">{experience.role}</h3>
<ul className="experience-tasks">
{tasks.map((task) => (
<li>{task.description}</li>
))}
</ul>
</div>
</div>
);
}
export default SingleExperience;
@@ -0,0 +1,25 @@
#skills-section{
display: flex;
flex-direction: column;
scroll-margin-top: 80px;
margin-top: 100px;
}
.skills-span{
width: 100%;
}
.skill-category{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin-bottom: 2%;
}
.skills{
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
@@ -0,0 +1,52 @@
import React, { useState, useEffect } from 'react';
import SkillCard from "../../../../components/SkillCard/SkillCard.jsx";
import "./Skills.css";
function Skills() {
const [skills, setSkills] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
const fetchSkills = async () => {
try {
const response = await fetch('/api/skills/');
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
const data = await response.json();
setSkills(data.data);
} catch (err) {
setError(err.message);
}
};
fetchSkills();
}, []);
if (error) {
return <div>Error retrieving data: {error}</div>;
}
const uniqueSkillTypes = [...new Set(skills.map(skill => skill.type))];
return (
<section id="skills-section">
<h1 className="section-title">Skills</h1>
{uniqueSkillTypes.map(type => (
<div id="languages" className="skill-category">
<h2>{type}</h2>
<div className="skills">
{skills
.filter(skill => skill.type === type)
.map(skill => (
<SkillCard text={skill.name}/>
))}
</div>
</div>
))}
</section>
)
}
export default Skills