Compare commits

...

30 Commits

Author SHA1 Message Date
543198994b feat: add Plausible support
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 46s
2025-05-15 20:29:03 +02:00
Morph01
b9ce2ffdc2 Add multi-languages support with i18next
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 7s
2025-03-04 21:39:02 +01:00
Morph01
069be079eb the CI file changed its name unintentionally ^^
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 36s
2024-11-23 19:04:06 +01:00
aac41fd363 Update build.yml with test deploy with brain
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 39s
2024-11-23 16:47:59 +00:00
dff4093315 Update build.yml with test deploy
All checks were successful
Linux arm64 / Build-and-Deploy (push) Successful in 34s
2024-11-23 16:33:16 +00:00
1be90da3c3 Update build.yml with test deploy
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 34s
2024-11-23 16:31:14 +00:00
1588363d97 Update build.yml with test deploy with brain
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 38s
2024-11-23 16:27:55 +00:00
0c64ba030c Update build.yml with test deploy
Some checks failed
Linux arm64 / Build-and-Deploy (push) Failing after 38s
2024-11-23 16:26:00 +00:00
d630bb4812 Update build.yml
All checks were successful
Linux arm64 / Build (push) Successful in 37s
2024-11-23 15:50:07 +00:00
c067f0b437 test another ssh key
Some checks failed
Linux arm64 / Build (push) Failing after 35s
2024-11-06 15:54:13 +00:00
Morph01
21355ac913 feat: add pipeline
Some checks failed
Linux arm64 / Build (push) Failing after 36s
2024-11-06 12:35:34 +01:00
Morph01
1f650249a3 chore: up to 1.1 with npm updated packages 2024-11-05 21:11:44 +01:00
Morph01
9c9860c80e fix: correct path and add better favicon 2024-11-05 21:06:05 +01:00
Morph01
2efe845306 feat: Add skills in My Skills 2024-11-05 21:05:33 +01:00
Morph01
7e14b570eb feat: Update infos on About Me 2024-11-05 21:04:37 +01:00
Morph01
b48bd9f372 fix: Update JSX attributes to use camelCase convention 2024-11-05 21:02:49 +01:00
Morph01
1a917475c6 last files 2024-02-14 15:08:26 +01:00
Morph01
40e0c9a528 better index.html, add preview image, description, title 2024-02-14 15:05:18 +01:00
Morph01
b9b290177a index page updated 2024-02-11 20:47:39 +01:00
Morph01
f47aa53976 some more styles 2024-02-11 20:47:04 +01:00
Morph01
2a998c7adf more data for sections 2024-02-11 20:46:17 +01:00
Morph01
7d3ae56c23 add section MyPorfolio, section ContactMe, section Footer 2024-02-11 20:45:10 +01:00
Morph01
98240d9898 better AboutMe, better HeroSection, better Navbar 2024-02-11 20:43:48 +01:00
Morph01
01724f3542 more img 2024-02-11 20:42:04 +01:00
Morph01
98a8bdcc5c default readme 2024-02-10 19:38:34 +01:00
Morph01
0417e82741 data for sections 2024-02-10 19:37:26 +01:00
Morph01
97a085350d index page 2024-02-10 19:36:47 +01:00
Morph01
217c1508a6 section My Portfolio in progression 2024-02-10 19:36:35 +01:00
Morph01
08457d6b91 add section Hero Section, section Skills, section About Me and the Navbar 2024-02-10 19:35:38 +01:00
Morph01
689be873fc styles css 2024-02-10 19:32:18 +01:00
37 changed files with 19160 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
name: Linux arm64
run-name: Build and Deploy Portfolio
on: [push]
jobs:
Build-and-Deploy:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Install dependencies and build
run: |
npm ci
npm run build
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_KEY_PORTFOLIO }}
- name: Add remote host to known_hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H git.ale-pri.com >> ~/.ssh/known_hosts
- name: Upload build folder to temporary directory on remote server
run: |
scp -r build ubuntu@git.ale-pri.com:Poubelle/portfolio
- name: Deploy to final directory on remote server
run: |
ssh ubuntu@git.ale-pri.com << 'EOF'
BUILD_TMP=Poubelle/portfolio
DEPLOY_DIR=/var/www/portfolio
sudo mkdir -p $DEPLOY_DIR
sudo rsync -a --delete $BUILD_TMP/ $DEPLOY_DIR/
sudo chown -R www-data:www-data $DEPLOY_DIR
sudo chmod -R 755 $DEPLOY_DIR
sudo rm -rf $BUILD_TMP
sudo nginx -t && sudo systemctl reload nginx
EOF

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

70
README.md Normal file
View File

@@ -0,0 +1,70 @@
# Getting Started with Create React App on my Portfolio 😎
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

17576
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

40
package.json Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "portfolio",
"version": "0.1.1",
"private": true,
"engines": {
"node": ">=12.x"
},
"dependencies": {
"@types/react-router-dom": "^5.3.3",
"i18next": "^22.5.1",
"i18next-browser-languagedetector": "^8.1.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-i18next": "^10.0.0",
"react-router-dom": "^7.6.0",
"react-scripts": "^5.0.1",
"react-scroll": "^1.9.3",
"typescript": "^4.9.5",
"web-vitals": "^5.0.1"
},
"devDependencies": {
"@babel/plugin-transform-private-property-in-object": "^7.27.1"
},
"scripts": {
"start": "react-scripts --openssl-legacy-provider start",
"build": "react-scripts build"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

BIN
public/img/cinetour.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

BIN
public/img/docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
public/img/favicon_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/img/gauss.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
public/img/gauss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
public/img/git.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/img/java.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/img/jira.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
public/img/kubernetes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/img/logo_blanc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
public/img/moi.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

BIN
public/img/mysql.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/img/nuitinfo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

27
public/index.html Normal file
View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/img/favicon_logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Portfolio de Thibaut ALESSI" />
<meta property="og:image" content="%PUBLIC_URL%/img/moiherosection.jpg" data-rh="true" />
<meta property="og:description" content="Portfolio de Thibaut ALESSI" data-rh="true">
<meta property="og:title" content="Portfolio" data-rh="true">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Portfolio</title>
<!-- Plausible -->
<script defer data-domain="thibaut.ale-pri.com"
src="https://plausible.ale-pri.com/js/script.file-downloads.hash.outbound-links.js"></script>
<script>window.plausible = window.plausible || function () { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

25
public/manifest.json Normal file
View File

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

3
public/robots.txt Normal file
View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

654
src/App.css Normal file
View File

@@ -0,0 +1,654 @@
/* Global CSS */
body {
margin: 0;
font-family: "Roboto", sans-serif;
-webkit-font-smoothing: "Roboto", sans-serif;
-moz-osx-font-smoothing: "Roboto", sans-serif;
font-style: normal;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin: 0;
}
:root {
--primary: #5e3bee;
--heading-color: #282938;
--bg-shade: #f5fcff;
--github: #e62872;
--darkblue: #1c1e53;
--black: #000000;
--white: #ffffff;
}
.btn {
font-family: "Roboto";
display: inline-block;
padding: 14px 32px;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
cursor: pointer;
text-align: center;
text-decoration: none;
border-radius: 4px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
transition: background-color 0.5s;
-webkit-transition: background-color 0.5s;
-moz-transition: background-color 0.5s;
-ms-transition: background-color 0.5s;
-o-transition: background-color 0.5s;
}
.btn-outline-primary {
color: var(--primary);
background-color: var(--white);
border: 1px solid var(--primary);
}
.btn-outline-primary:hover {
color: var(--white);
background-color: var(--primary);
}
.btn-primary {
color: var(--white);
background-color: var(--primary);
border: 1px solid var(--primary);
}
.btn-primary:hover {
color: var(--primary);
background-color: var(--white);
}
.btn-github {
color: var(--white);
background-color: var(--github);
border: var(--github);
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.95);
gap: 16px;
}
.btn-github:hover {
color: var(--github);
background-color: var(--white);
}
/* Global CSS Ends */
/* Main Headings */
/* Heading 1 */
h1 {
font-size: 56px;
font-weight: 700;
line-height: 67px;
}
/* Heading 2 */
h2 {
font-size: 48px;
font-weight: 700;
line-height: 58px;
}
/* Heading 3 */
h2 {
font-size: 24px;
font-weight: 700;
line-height: 34px;
}
/* Pragraphs text large medium small */
/* Body 1 */
.text-lg {
color: var(--darkblue);
font-size: 18px;
font-style: normal;
font-weight: 400;
line-height: 27px;
}
/* Body 2 */
.text-md {
color: var(--darkblue);
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
}
/* Body 3 */
.text-sm {
color: var(--black);
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 21px;
}
/* Section Titles */
/* Skills & About Me */
.section--title {
color: var(--heading-color);
font-size: 21px;
text-align: center;
font-style: normal;
font-weight: 600;
line-height: 32px;
display: flex;
align-items: flex-start;
}
/* Portfolio & Contact Me */
.sub--title {
color: var(--heading-color);
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
/* Section Titles Ends */
/* Navbar Style Start */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 85.333px;
background: var(--white);
box-shadow: 0px 5.333px 80px 0 rgba(0, 0, 0, 0.1);
position: fixed;
top: 0;
left: 0;
right: 0;
}
.navbar--items > ul {
list-style: none;
display: flex;
align-items: flex-start;
gap: 42.667px;
text-decoration: none;
}
.navbar--items ul > li > a {
text-decoration: none;
}
/* Navbar Content */
.navbar--content {
color: var(--darkblue);
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
.navbar--active-content {
color: var(--primary);
}
/* Navbar Styler Ends */
/* Hero Section Style */
.hero--section {
display: grid;
grid-template-columns: repeat(2, 1fr);
padding: 133.333px 85.333px 133.333px;
align-items: center;
justify-content: space-between;
gap: 32px;
background-color: var(--bg-shade);
}
.hero--section--content-box {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 32px;
}
.hero--section--content {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 21.333px;
}
.hero--section--content--box > button {
margin-top: 21.333px;
}
.hero--section--title {
color: var(--heading-color);
font-size: 74.667px;
font-weight: 700;
line-height: 90px;
align-self: stretch;
}
.hero--section--title--color {
color: var(--primary);
}
.hero--section-description {
color: var(--darkblue);
font-size: 24px;
font-weight: 400;
line-height: 36px;
}
.hero--section--img {
display: flex;
}
.hero--section--img > img {
width: 100%;
height: 100%;
}
/* Hero Section Style Ends */
/* Skills Section Style */
.skills--section {
display: flex;
padding: 149.33px 85.33px;
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 106.667px;
}
.skills--section--heading {
color: var(--heading-color);
font-size: 64px;
font-weight: 700;
line-height: 77px;
}
.skills--section--container {
display: grid;
justify-content: center;
align-items: flex-start;
gap: 42.6px;
grid-template-columns: repeat(4, 1fr);
}
.skills--section--card {
display: flex;
padding: 32px;
flex-direction: column;
align-items: flex-start;
gap: 32px;
flex: 1 0 0;
border-radius: 10.6px;
background: var(--bg-shade);
min-height: 250px;
}
.skills--section--card:hover {
border-bottom: 4px solid var(--primary);
}
.skills--section--card:hover .skills--section--description {
color: var(--darkblue);
}
.skills--section--img {
display: flex;
padding: 13.3px;
justify-content: center;
align-items: center;
gap: 13.3px;
border-radius: 10.6px;
background: #fff;
box-shadow: 0 0 16px 0 rgba(0, 0, 0, 0.1);
}
.skills--section--card--content {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 32px;
align-self: stretch;
}
.skills--section--title {
color: var(--heading-color);
font-size: 32px;
font-weight: 700;
line-height: 45px;
}
.skills--section--description {
color: var(--black);
font-size: 21.3px;
font-style: normal;
font-weight: 400;
line-height: 32px;
}
/* Skills Style Ends */
/* About Us Starts*/
.about--section {
display: grid;
padding: 133.3px 85.3px;
align-items: center;
gap: 114.6px;
grid-template-columns: repeat(2, 1fr);
}
.about--section--img > img {
width: 100%;
height: 100%;
}
/* About Us Ends */
/* My Portfolio Starts */
.portfolio--section {
display: flex;
padding: 112px 85px;
flex-direction: column;
align-items: flex-start;
gap: 80px;
}
.portfolio--container-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.portfolio--container {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 21.3px;
}
.portfolio--section--container {
display: flex;
align-items: center;
justify-content: center;
gap: 42.6px;
width: 100%;
}
.portfolio--section--img {
border-radius: 8px;
width: 100%;
}
.portfolio--section--img > img {
width: 100%;
}
.portfolio--section--card {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 32px;
flex: 1 0 0;
background: #fff;
box-shadow: 0 0 32px 0 rgba(0, 0, 0, 0.15);
cursor: pointer;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
}
.portfolio--section--card--content {
display: flex;
padding: 32px;
flex-direction: column;
align-items: flex-start;
gap: 32px;
align-self: stretch;
}
.portfolio--section--title {
color: var(--heading-color);
}
.portfolio--link {
text-decoration: none;
display: flex;
gap: 16px;
border-bottom: 1.33px solid var(--primary);
padding-bottom: 10.6px;
font-weight: 600;
}
.portfolio--section--card:hover path {
stroke: #006b6a;
}
/* Portfolio Ends */
/* Contact Me Starts*/
.contact--section {
display: flex;
padding: 150px 85px;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 64px;
}
.text-lg-with-margin {
color: var(--darkblue);
font-size: 18px;
font-style: normal;
font-weight: 400;
line-height: 27px;
margin-top: 15px;
}
/* Contact End */
/* Footer Start */
/* Footer Starts */
.footer--container {
display: flex;
padding: 106.667px 85.333px;
flex-direction: column;
align-items: flex-start;
background: var(--bg-shade);
align-items: center;
align-self: stretch;
}
.footer--link--container {
display: flex;
justify-content: space-between;
align-items: center;
align-self: stretch;
}
.footer--items > ul {
list-style: none;
display: flex;
align-items: flex-start;
gap: 42.667px;
text-decoration: none;
}
.footer--items ul > li > a {
text-decoration: none;
}
.footer--social--icon > ul {
list-style: none;
display: flex;
justify-content: flex-end;
align-items: center;
gap: 16px;
flex-shrink: 0;
text-decoration: none;
}
.divider {
margin: 106px 0 42.67px;
height: 1.333px;
width: 100%;
background: rgba(40, 41, 56, 0.55);
}
.footer--content--container {
display: flex;
justify-content: space-between;
align-items: center;
align-self: stretch;
}
.footer--content {
color: var(--black);
font-size: 18.667px;
font-weight: 400;
line-height: 28px;
}
/* Responsive Screens */
@media only screen and (max-width: 1800px) {
.hero--section--title {
font-size: 68px;
line-height: 70px;
}
.skills--section--title {
font-size: 28px;
line-height: 40px;
}
}
@media only screen and (max-width: 1600px) {
.skills--section--heading {
font-size: 54px;
line-height: 70px;
}
.skills--section--container {
gap: 16px;
}
.skills--section--card {
gap: 28px;
}
.skills--section--card--content {
gap: 20px;
}
.skills--section--title {
font-size: 23px;
line-height: 30px;
}
.skills--section--description {
font-size: 17.333px;
line-height: 27px;
}
}
@media only screen and (max-width: 1200px) {
.btn-outline-primary {
display: none;
}
.hero--section {
display: flex;
flex-direction: column-reverse;
padding-bottom: 70px;
}
.hero--section--title,
.hero--section-description,
.footer--content {
text-align: center;
}
.skills--section--container,
.about--section,
.portfolio--section--container,
.portfolio--container-box,
.footer--link--container,
.footer--items > ul,
.footer--content--container {
display: flex;
flex-direction: column;
}
.skills--section,
.portfolio--container,
.hero--section--content,
.hero--section--content--box {
align-items: center;
}
.portfolio--container-box {
gap: 30px;
}
.skills--section,
.testimonial--section,
.contact--section,
.footer--container {
gap: 20px;
padding-top: 70px;
padding-bottom: 70px;
}
.about--section {
gap: 20px;
padding-top: 0;
padding-bottom: 0;
}
.testimonial--section--card {
padding: 25px;
}
.hero--section--title,
.skills--section--heading,
.sections--heading {
font-size: 35px;
line-height: 40px;
}
.hero--section--content--box {
gap: 10px;
}
.contact--form--container {
width: 100%;
}
.container {
display: flex;
flex-direction: column;
gap: 10px;
}
.footer--social--icon > ul,
.footer--items > ul {
padding: 0;
align-items: center;
}
.divider {
margin: 20px;
}
}
/* Hamburger menu */
.nav__hamburger {
display: none;
width: 1.875rem;
height: 1.313rem;
flex-direction: column;
justify-content: space-around;
position: absolute;
top: 25px;
right: 25px;
}
.nav__hamburger__line {
display: block;
height: 0.188rem;
width: 100%;
background-color: #000000;
border-radius: 0.625rem;
transition: all ease-in-out 0.2s;
}
@media screen and (max-width: 1200px) {
.nav__hamburger {
display: flex;
z-index: 200;
}
.navbar--items {
display: flex;
}
.navbar--items {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255, 255, 255);
top: -20rem;
left: 0;
width: 100%;
transition: all ease-in-out 0.4s;
}
.navbar--items ul {
flex-direction: column;
align-items: center;
width: 100%;
padding: 3rem 0 0.6rem;
z-index: -100;
}
.navbar--items ul li {
text-align: center;
}
.navbar--items ul li a {
padding: 0.5rem;
}
.navbar--items {
z-index: -1000;
}
.navbar--items.active {
top: 30px;
}
.nav__hamburger.active :nth-child(1) {
transform: rotate(45deg) translate(0.45rem, 0.1875rem);
}
.nav__hamburger.active :nth-child(2) {
opacity: 0;
}
.nav__hamburger.active :nth-child(3) {
transform: rotate(-45deg) translate(0.45rem, -0.1875rem);
}
}
/* Responsive Screens Ends*/

View File

@@ -3,6 +3,7 @@ import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Home from "./Pages/Home/Homescreen";
import Navbar from "./Pages/Home/Navbar";
import "./i18n";
function App() {
return (

View File

@@ -0,0 +1,25 @@
import { useTranslation } from "react-i18next";
export default function AboutMe() {
const { t } = useTranslation();
return (
<section id="AboutMe" className="about--section">
<div className="about--section--img">
<img src="./img/moi.jpg" alt="AboutMe" />
</div>
<div className="hero--section--content-box about--section--box">
<div className="hero--section--content">
<p className="section--title">{t('about.title')}</p>
<h1 className="skills-section--heading">{t('about.heading')}</h1>
<p className="hero--section-description">
{t('about.description1')}
</p>
<p className="hero--section-description">
{t('about.description2')}
</p>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,21 @@
import { useTranslation } from "react-i18next";
export default function ContactMe() {
const { t } = useTranslation();
return (
<section id="Contact" className="contact--section">
<div>
<p className="sub--title">{t('contact.title')}</p>
<h2>{t('contact.heading')}</h2>
<p className="text-lg-with-margin">
{t('contact.description1')}
</p>
<a href="mailto:thibaut.alessi@free.fr">thibaut.alessi@free.fr</a>
<p className="text-lg">
{t('contact.description2')}
</p>
</div>
</section>
);
}

102
src/Pages/Home/Footer.jsx Normal file
View File

@@ -0,0 +1,102 @@
import { Link } from "react-scroll";
import React from "react";
import { useTranslation } from "react-i18next";
function Footer() {
const { t } = useTranslation();
return (
<footer className="footer--container">
<div className="footer--link--container">
<Link
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="footer--logo"
style={{ cursor: 'pointer' }}
>
<img src="./img/logo.png" alt="Logo" />
</Link>
<div className="footer--items">
<ul>
<li>
<Link
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="text-md"
style={{ cursor: 'pointer' }}
>
{t('footer.home')}
</Link>
</li>
<li>
<Link
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="MyPortfolio"
className="text-md"
style={{ cursor: 'pointer' }}
>
{t('footer.portfolio')}
</Link>
</li>
<li>
<Link
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="AboutMe"
className="text-md"
style={{ cursor: 'pointer' }}
>
{t('footer.about')}
</Link>
</li>
</ul>
</div>
<div className="footer--social--icon">
<ul>
<li>
<a
href="https://www.linkedin.com/in/thibautalessi/"
className="navbar--content"
target="_blank"
rel="noreferrer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 33 33"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.33341 4.65479H26.0001C27.4729 4.65479 28.6667 5.84869 28.6667 7.32145V25.9881C28.6667 27.4609 27.4729 28.6548 26.0001 28.6548H7.33341C5.86065 28.6548 4.66675 27.4609 4.66675 25.9881V7.32145C4.66675 5.84869 5.86065 4.65479 7.33341 4.65479ZM11.3334 24.6548C11.7016 24.6548 12.0001 24.3563 12.0001 23.9881V14.6548C12.0001 14.2867 11.7016 13.9881 11.3334 13.9881H9.33342C8.96523 13.9881 8.66675 14.2867 8.66675 14.6548V23.9881C8.66675 24.3563 8.96523 24.6548 9.33342 24.6548H11.3334ZM10.3334 12.6548C9.22884 12.6548 8.33341 11.7594 8.33341 10.6548C8.33341 9.55021 9.22884 8.65479 10.3334 8.65479C11.438 8.65479 12.3334 9.55021 12.3334 10.6548C12.3334 11.7594 11.438 12.6548 10.3334 12.6548ZM24.0001 24.6548C24.3682 24.6548 24.6667 24.3563 24.6667 23.9881V17.8548C24.7101 15.7359 23.1435 13.9275 21.0401 13.6681C19.5694 13.5338 18.1445 14.2207 17.3334 15.4548V14.6548C17.3334 14.2867 17.0349 13.9881 16.6667 13.9881H14.6667C14.2986 13.9881 14.0001 14.2867 14.0001 14.6548V23.9881C14.0001 24.3563 14.2986 24.6548 14.6667 24.6548H16.6667C17.0349 24.6548 17.3334 24.3563 17.3334 23.9881V18.9881C17.3334 17.8836 18.2289 16.9881 19.3334 16.9881C20.4379 16.9881 21.3334 17.8836 21.3334 18.9881V23.9881C21.3334 24.3563 21.6319 24.6548 22.0001 24.6548H24.0001Z"
fill="black"
/>
</svg>
</a>
</li>
</ul>
</div>
</div>
</footer>
);
}
export default Footer;

View File

@@ -0,0 +1,30 @@
import { useTranslation } from "react-i18next";
export default function HeroSection() {
const { t } = useTranslation();
return (
<section id="heroSection" className="hero--section">
<div className="hero--section--content-box">
<div className="hero--section--content">
<p className="section--title">{t('hero.hello')}</p>
<h1 className="hero--section--title">
<span className="hero--section--title--color">
{t('hero.student')}
</span>{" "}
<br />
{t('hero.passion')}
</h1>
<p className="hero--section--description">
{t('hero.description')}
<br />
{t('hero.goal')}
</p>
</div>
</div>
<div className="hero--section--img">
<img src="./img/moiherosection.jpg" alt="Hero Section" />
</div>
</section>
);
}

View File

@@ -0,0 +1,19 @@
import AboutMe from "../AboutMe";
import ContactMe from "../ContactMe";
import Footer from "../Footer";
import HeroSection from "../HeroSection";
import MyPortfolio from "../MyPortfolio";
import MySkills from "../MySkills";
export default function Home() {
return (
<>
<HeroSection />
<MySkills />
<AboutMe />
<MyPortfolio />
<ContactMe />
<Footer />
</>
);
}

View File

@@ -0,0 +1,78 @@
import data from "../../data/index.json";
import { useTranslation } from "react-i18next";
export default function MyPortfolio() {
const { t, i18n } = useTranslation();
const currentLang = (i18n.language || 'fr').split('-')[0];
const openLinkInNewTab = (link) => {
window.open(link, "_blank");
};
return (
<section className="portfolio--section" id="MyPortfolio">
<div className="portfolio--container-box">
<div className="portfolio--container">
<p className="sub--title">{t('portfolio.title')}</p>
<h2 className="section--heading">{t('portfolio.heading')}</h2>
</div>
<div>
<button className="btn btn-github" onClick={() => openLinkInNewTab("https://github.com/Morph01")}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 33 33"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16.3333 0.166748C7.50028 0.166748 0.333252 7.33378 0.333252 16.1667C0.333252 24.9997 7.50028 32.1667 16.3333 32.1667C25.1489 32.1667 32.3333 24.9997 32.3333 16.1667C32.3333 7.33378 25.1489 0.166748 16.3333 0.166748ZM26.9016 7.54202C28.8105 9.8674 29.9559 12.8348 29.9906 16.0452C29.5394 15.9585 25.0274 15.0387 20.4808 15.6114C20.3767 15.3858 20.2899 15.1428 20.1858 14.8999C19.9081 14.2405 19.5958 13.5637 19.2834 12.9216C24.3159 10.8739 26.6066 7.9238 26.9016 7.54202ZM16.3333 2.52684C19.804 2.52684 22.9797 3.82836 25.3919 5.96285C25.1489 6.30992 23.0838 9.06914 18.2248 10.8912C15.9862 6.77846 13.5047 3.41187 13.1229 2.89126C14.1467 2.64831 15.2227 2.52684 16.3333 2.52684ZM10.5199 3.811C10.8843 4.2969 13.3138 7.68085 15.5871 11.7068C9.20093 13.4075 3.56102 13.3728 2.95364 13.3728C3.83867 9.13855 6.70201 5.61577 10.5199 3.811ZM2.65863 16.1841C2.65863 16.0452 2.65863 15.9064 2.65863 15.7676C3.24865 15.7849 9.87772 15.8717 16.6977 13.824C17.0969 14.5875 17.4613 15.3684 17.8084 16.1493C17.6348 16.2014 17.4439 16.2535 17.2704 16.3055C10.2248 18.5788 6.47642 24.7914 6.16405 25.312C3.99485 22.8999 2.65863 19.6895 2.65863 16.1841ZM16.3333 29.8413C13.1749 29.8413 10.2595 28.7654 7.95147 26.9606C8.19442 26.4574 10.971 21.1125 18.676 18.4227C18.7107 18.4053 18.7281 18.4053 18.7628 18.388C20.689 23.3684 21.47 27.5506 21.6782 28.748C20.0296 29.4595 18.2248 29.8413 16.3333 29.8413ZM23.9515 27.4986C23.8127 26.6656 23.0838 22.6743 21.2964 17.7632C25.5828 17.0864 29.3311 18.1971 29.7997 18.3533C29.2097 22.1537 27.0231 25.4335 23.9515 27.4986Z"
fill="currentColor"
/>
</svg>
{t('portfolio.github')}
</button>
</div>
</div>
<div className="portfolio--section--container">
{data?.portfolio?.map((item, index) => (
<div key={index} className="portfolio--section--card"
onClick={() => openLinkInNewTab(item.link)}
style={{ cursor: 'pointer' }}>
<div className="portfolio--section--img">
<img src={item.src} alt={item.title[currentLang]} />
</div>
<div className="portfolio--section--card--content">
<div>
<h3 className="portfolio--section--title">
{item.title[currentLang]}
</h3>
<p className="text-md">{item.description[currentLang]}</p>
</div>
<p className="text-sm portfolio--link">
{item.voir[currentLang]}
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 20 19"
fill="none"
>
<path
d="M4.66667 1.66675H18V15.0001M18 1.66675L2 17.6667L18 1.66675Z"
stroke="currentColor"
strokeWidth="2.66667"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</p>
</div>
</div>
))}
</div>
</section>
);
}

View File

@@ -0,0 +1,29 @@
import { useTranslation } from "react-i18next";
import data from "../../data/index.json";
export default function MySkills() {
const { t, i18n } = useTranslation();
const currentLang = (i18n.language || 'fr').split('-')[0];
return (
<section className="skills--section" id="mySkills">
<div className="portfolio--container">
<p className="section--title">{t('skills.title')}</p>
<h2 className="skills--section--heading">{t('skills.heading')}</h2>
</div>
<div className="skills--section--container">
{data?.skills?.map((item, index) => (
<div key={index} className="skills--section--card">
<div className="skills--section--img">
<img src={item.src} alt="Product Chain" />
</div>
<div className="skills--section--card--content">
<h3 className="skills--section--title">{item.title[currentLang]}</h3>
<p className="skills--section--description">{item.description[currentLang]}</p>
</div>
</div>
))}
</div>
</section>
);
}

122
src/Pages/Home/Navbar.jsx Normal file
View File

@@ -0,0 +1,122 @@
import { useState, useEffect } from "react";
import { Link } from "react-scroll";
import { useTranslation } from "react-i18next";
function Navbar() {
const [navActive, setNavActive] = useState(false);
const { t } = useTranslation();
const toggleNav = () => {
setNavActive(!navActive);
};
const closeMenu = () => {
setNavActive(false);
};
useEffect(() => {
const handleResize = () => {
if (window.innerWidth <= 500) {
closeMenu;
}
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
useEffect(() => {
if (window.innerWidth <= 1200) {
closeMenu;
}
}, []);
return (
<nav className={`navbar ${navActive ? "active" : ""}`}>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={false}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="navbar--logo"
style={{ cursor: 'pointer' }}
>
<img src="./img/logo.png" alt="Logo" />
</Link>
<a
className={`nav__hamburger ${navActive ? "active" : ""}`}
onClick={toggleNav}
>
<span className="nav__hamburger__line"></span>
<span className="nav__hamburger__line"></span>
<span className="nav__hamburger__line"></span>
</a>
<div className={`navbar--items ${navActive ? "active" : ""}`}>
<ul>
<li>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="heroSection"
className="navbar--content"
>
{t('navbar.home')}
</Link>
</li>
<li>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="MyPortfolio"
className="navbar--content"
>
{t('navbar.portfolio')}
</Link>
</li>
<li>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="AboutMe"
className="navbar--content"
>
{t('navbar.about')}
</Link>
</li>
</ul>
</div>
<Link
onClick={closeMenu}
activeClass="navbar--active-content"
spy={true}
smooth={true}
offset={-70}
duration={500}
to="Contact"
className="btn btn-outline-primary"
>
{t('navbar.contact')}
</Link>
</nav>
);
}
export default Navbar;

153
src/data/index.json Normal file
View File

@@ -0,0 +1,153 @@
{
"skills": [
{
"id": "1",
"src": "./img/cpp.png",
"title": {
"fr": "POO (Programmation Orientée Objet)",
"en": "OOP (Object-Oriented Programming)"
},
"description": {
"fr": "Développement en C++ du jeu Blitz.",
"en": "Development of the Blitz game in C++."
}
},
{
"id": "2",
"src": "./img/sql.png",
"title": {
"fr": "Base de Données et SGBD MySQL",
"en": "Databases and MySQL DBMS"
},
"description": {
"fr": "Utilisation du SGBD MySQL pour le projet de mise en place d'une base de données pour le jeu Blitz.",
"en": "Using MySQL DBMS for implementing a database for the Blitz game."
}
},
{
"id": "3",
"src": "./img/html-css.png",
"title": {
"fr": "Front-End",
"en": "Front-End"
},
"description": {
"fr": "Développement de l'interface Front-End du site de notre participation à la Nuit de l'Info 2024 en HTML, SCSS, ReactJS + Vite.",
"en": "Development of the Front-End interface for our 'Nuit de l'Info 2024' participation website using HTML, SCSS, ReactJS + Vite."
}
},
{
"id": "4",
"src": "./img/java.png",
"title": {
"fr": "POO (Programmation Orientée Objet)",
"en": "OOP (Object-Oriented Programming)"
},
"description": {
"fr": "Développement et compréhension de code JAVA, accordé avec Maven et Hibernate par exemple.",
"en": "Development and understanding of JAVA code, combined with tools like Maven and Hibernate."
}
},
{
"id": "5",
"src": "./img/jira.png",
"title": {
"fr": "Gestion de Projet / Méthodes agiles / ITIL",
"en": "Project Management / Agile Methods / ITIL"
},
"description": {
"fr": "Compréhension et application au quotidien de méthodes agiles, processus ITIL.",
"en": "Understanding and daily application of agile methods and ITIL processes."
}
},
{
"id": "6",
"src": "./img/git.png",
"title": {
"fr": "Git",
"en": "Git"
},
"description": {
"fr": "Utilisation de Git pour la gestion de version de tout mes projets.",
"en": "Using Git for version control of all my projects."
}
},
{
"id": "7",
"src": "./img/docker.png",
"title": {
"fr": "Docker",
"en": "Docker"
},
"description": {
"fr": "Utilisation de Docker pour mettre en place des conteneurs pour mes projets et expérience de la conteneurisation de diverses applications chez Worldline.",
"en": "Use of Docker to set up containers for my projects and experienced containerization of various applications at Worldline."
}
},
{
"id": "8",
"src": "./img/kubernetes.png",
"title": {
"fr": "Kubernetes",
"en": "Kubernetes"
},
"description": {
"fr": "Utilisation de Kubernetes pour la gestion de conteneurs d'une plateforme de plusieurs applications sur GCP (Google Cloud Platform).",
"en": "Using Kubernetes to manage containers for a multi-application platform on GCP (Google Cloud Platform)."
}
}
],
"portfolio": [
{
"id": "1",
"src": "./img/cinetour.png",
"title": {
"fr": "Cinetour",
"en": "Cinetour"
},
"description": {
"fr": "Une application web pour les cinéphiles et les amateurs de voyage pour explorer les lieux réels où leurs films préférés ont été tournés. Développée avec Java (Spring Boot), React Frontend, MySQL, Dockerisée et hébergée sur un serveur cloud personnel.",
"en": "A web application for cinephiles and travel enthusiasts to explore the real-life locations where their favorite films were shot. Developed with Java (Spring Boot), React Frontend, MySQL, Dockerized and hosted on a personal cloud server."
},
"voir": {
"fr": "Découvrir",
"en": "Discover"
},
"link": "https://cinetour.ale-pri.com"
},
{
"id": "2",
"src": "./img/blitz.jpg",
"title": {
"fr": "Blitz",
"en": "Blitz"
},
"description": {
"fr": "Jeu 3D multijoueurs cross-platforme (Windows, Linux, MacOS, Android) développé en C++, interface 3D avec OpenGL, interface utilisateur avec ImGui.",
"en": "Cross-platform multiplayer 3D game (Windows, Linux, MacOS, Android) developed in C++, 3D interface with OpenGL, user interface with ImGui."
},
"voir": {
"fr": "Voir Sur Gitea",
"en": "View On Gitea"
},
"link": "https://git.ale-pri.com/Blitz/Blitz"
},
{
"id": "3",
"src": "./img/gauss.jpg",
"title": {
"fr": "Elimination de Gauss-Jordan",
"en": "Gauss-Jordan Elimination"
},
"description": {
"fr": "Utilisation C++ pour effectuer plusieurs opérations sur des matrices afin de trouver le noyau et l'image d'applications linéaires par la méthode du pivot de Gauss",
"en": "Using C++ to perform various operations on matrices to find the kernel and image of linear applications using the Gaussian pivot method"
},
"voir": {
"fr": "Voir Sur Gitea",
"en": "View On Gitea"
},
"link": "https://git.ale-pri.com/ProjetMAM/Pivot"
}
]
}

32
src/i18n/index.js Normal file
View File

@@ -0,0 +1,32 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import translationEN from './locales/en.json';
import translationFR from './locales/fr.json';
const resources = {
en: {
translation: translationEN
},
fr: {
translation: translationFR
}
};
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources,
fallbackLng: 'fr',
detection: {
order: ['navigator', 'htmlTag', 'path', 'subdomain'],
caches: ['localStorage']
},
interpolation: {
escapeValue: false
}
});
export default i18n;

41
src/i18n/locales/en.json Normal file
View File

@@ -0,0 +1,41 @@
{
"navbar": {
"home": "Home",
"portfolio": "Portfolio",
"about": "About Me",
"contact": "Contact Me"
},
"hero": {
"hello": "Hello, I'm ALESSI Thibaut",
"student": "Student at Polytech Lyon",
"passion": "SRE/OPS apprentice at WORLDLINE",
"description": "I love Java, Docker, guitar, chess, sports, and traveling.",
"goal": "My goal is to improve every day."
},
"skills": {
"title": "My Competencies",
"heading": "My Skills"
},
"about": {
"title": "About",
"heading": "About Me",
"description1": "Third-year engineering student at Polytech Lyon in Computer Science, working as an SRE/OPS engineer at WORLDLINE through an apprenticeship program.",
"description2": "Passionate about IT, I'm looking for an opportunity for a summer internship abroad to develop my skills and contribute to a company project, whether Cloud, Infrastructure, Development, OPS..."
},
"portfolio": {
"title": "Recent Projects",
"heading": "My Portfolio",
"github": "Visit my GitHub"
},
"contact": {
"title": "Get in Touch",
"heading": "Contact Me",
"description1": "If you want to contact me, you can send me an email at:",
"description2": "Or directly through LinkedIn at the bottom of the page."
},
"footer": {
"home": "Home",
"portfolio": "Portfolio",
"about": "About Me"
}
}

41
src/i18n/locales/fr.json Normal file
View File

@@ -0,0 +1,41 @@
{
"navbar": {
"home": "Accueil",
"portfolio": "Portfolio",
"about": "À propos de moi",
"contact": "Contactez Moi"
},
"hero": {
"hello": "Hello, je suis ALESSI Thibaut",
"student": "Etudiant à Polytech Lyon",
"passion": "Alternant SRE/OPS chez WORLDLINE",
"description": "J'aime Java, Docker, la guitare, les échecs, le sport et voyager.",
"goal": "Mon objectif, m'améliorer chaque jour."
},
"skills": {
"title": "Mes Compétences",
"heading": "Mes Skills"
},
"about": {
"title": "À propos",
"heading": "À propos de moi",
"description1": "Alternant en troisième année d'école d'ingénieur à Polytech Lyon en Informatique en alternance à WORLDLINE, occupant le poste d'ingénieur SRE/OPS.",
"description2": "Passionné d'informatique, je suis à la recherche d'une opportunité pour un stage d'été à l'étranger pour développer mes compétences et contribuer à un projet d'entreprise qu'il soit orienté Cloud, Infrastructure, Développement, OPS..."
},
"portfolio": {
"title": "Projets récents",
"heading": "Mon Portfolio",
"github": "Visiter mon GitHub"
},
"contact": {
"title": "Rentrer en Contact",
"heading": "Contactez Moi",
"description1": "Si vous voulez me contacter, vous pouvez m'envoyer un mail à l'adresse email suivante :",
"description2": "Ou bien directement par LinkedIn en bas de page."
},
"footer": {
"home": "Accueil",
"portfolio": "Portfolio",
"about": "À propos de moi"
}
}