Refactor: move frontend in apps/frontend

This commit is contained in:
Giovanni committed 2026-10-03 12:04:17 +02:00
1 parent 2ab10c7803
commit 6b36ab8bfa
88 files changed
+4 -4

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
../../.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+19
View File
@@ -0,0 +1,19 @@
# To do
- revoir fonction de tri par age car problème entre 1 date et 2 des fois
- Refaire les images qui vont pas
- Faire du responsive
- utiliser les vraies fonctions de fastapi
## Plus tard
- voir quoi mettre à droite des pages de details
- Régler problème de scroll entre page
- Refaire la section des skills
## Usefull commands
`npm install`
`npm run dev`
`npm install react-router-dom`
`npm install react-markdown remark-gfm`
+33
View File
@@ -0,0 +1,33 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
+18
View File
@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/assets/images/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Audiowide&display=swap" rel="stylesheet">
<title>Giovanni Josserand</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/apps/frontend/srcs/frontend/src/main.jsx"></script>
</body>
</html>
+4317
View File
File diff suppressed because it is too large. Load diff
+30
View File
@@ -0,0 +1,30 @@
{
"name": "portfolio",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint ../..",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.8.2",
"remark-gfm": "^4.0.1"
},
"devDependencies": {
"@eslint/js": "^9.25.0",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1",
"eslint": "^9.25.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.0.0",
"vite": "^6.3.5"
}
}
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="500"
height="500"
viewBox="0 0 500 500"
sodipodi:docname="logo.png"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g1">
<image
width="500"
height="500"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;XbnV2nTV4lt+duvFv7rlVxff8rPbLrJywY3fvvE8i+1ZGy7a8PQX7/zid+/64l1fZ9fvrV/1qlc9&#10;3ZL92ueff/5IDM/1TVZfEfrll18+Z999991ot9122+fZz97kQ9df/51P/eAHP7jipptuuvq22267&#10;+K677jr117/+9Un33XffW+6///5jbXiMTb/+nnvuOcqGR957772HIzZ+qJdf3XnHoXffe88hv/3t&#10;A4fcdecdB4+PrTr4yaWPHzw+vvrgW2/75cG3337LwWUzftDSpU8c9NSyJw8aG1t1oC07cHxs9QGr&#10;Vq84YMXq5V5eZ+Ne9rfx/VauXr7/8pUr9qsny2x5RPaLxPefir/OhrVygM2jzwNtH4QI8VhZtvKp&#10;A6fkIFvfyfLVyw5ysmrZwStWLUcOWm7DjOQQq+fQJFm2anli+fLZ5YfZvFhZtnL5oTVyWCRNPFae&#10;WrnsMGT5qmVW7yw5fHb+cmy2dZd7IR2RGTpo78T2cfgsWbHsiKcaycplh9POYnX4lBw2FZImjtCH&#10;tafaN+moHLFq9cojygNy5MP/+ueRt991+5F333PXkffe9+sj77r37iPvfeC+I//01z8euXJs1ZG/&#10;+f0DR/7tH389YsXq5UesGl91xMqJVUdgo8XhiCmJ6iVe028VF5tPfFltHZvv8sivylMrlh9+9313&#10;H3HH3bcf8Yc///HwSSkfvmzl8sOtHVZW0iYiTi9p2564G5OpMfAYRPOI+/wsQ/R6WWH7r4qd+yuQ&#10;g5evWhErK1atPGiWrF5pj91ZYo/rGXmkkZq6y23ayqrlVm+crLTH9ixbsPHQ5atWHLZy1YrDrRDG&#10;CWVVsT5Z7FfUivcfnfhs7Vg5LWMrDrLjedDKsRUHrxhbfujSFU8xx45+aMk/jv35Lb94+09v/skn&#10;f/KjH1/1ox/84NovXfelz53+8dP/56Uvfel+r371q599+OGHL+i33XxfEPree++94EUvetFeH/7w&#10;qed+//s//OIPf/jj8/785z//V6lU2n/ZsmW7rVy58gUTExNb2HueG9m89aysY3fwa42Pj69pw4VT&#10;ssCGyKgNkTVsuEZJSmsMlEprrB5bvYY9DXR5hFbHfFs2f6A0MH/OnDnzy6Y8X4zMHxgYmE/Z5OTk&#10;fMpsn/PqiRGZa8vSSH0dxsyz9tST+basacEPL1Ptne82Piu09q+RJHFtWs8rt9e/mFntE2wZtWWj&#10;1rdEoU5EovpTtW+kv1F5pG/XX226UfvJ8uTo+PjYqJ2/o3bMRwcHB0ft3HW6JiYnR+0cdnl2To+O&#10;DI+Mjtm69DE8NFxpIzLaqA9bXm+OuH7QV09Wr17l7MEObMS2ickJjs9RbK9pB/7oJEQa2lbTnrZN&#10;ifWtYR+2Tj3/G+Zb+/CjnkSP7Xp1EvNjbIvzZ4GtFydxddPkVf0eHBhcw44pNo7a9ZRxXWB9XnNo&#10;cGhtO9/Ws+Gzxicmtl69emxnY8ovf/jhfx59809/evb13/zWF7751a+f8eVrrtlr//33f8b1118/&#10;Ytv1/P+eJfRrr713+N///d83spfOX3fDDd+5/NZbbz/vL3/5y0HLlz+1ozGTzx4ZGVp3YmJs4dDQ&#10;0Fy7SA3aCTlgJ07JiiB25G2WCGGSlErG1h+39SbF6nTh8NCgrF69UoaHB2Vickxsn5V8mx4fXy22&#10;XxmfWC0iZZkoj+cqk2ZCipRG/mVr2+QsX5vqv9w8Vk3pjxmLRu07Wz4xay4ODJZk3M5hsfNcBky1&#10;3Ni5a6SC9+rxVTY1KZSXzaSr7/JsfLb9s/uYXWe82s9kDGa1eSV79JpSWUoD4uwYHhmSwWGbsDbX&#10;1q1NJ/U90cJ8aE7/tJ8TLa4Dtf1lnW7VrgzauTlQnppj+OXj6GZOrhpbKXbTVRqfGC+NjY8N2nV6&#10;xG6yFpZKA880ItsvXf7UQb++//7zv/3Nb37+P4/5z/fvsdseLzjmmGM4KbDrsa3dg/9LvebTjjvu&#10;OLTTTjttfeyxLznl5pt/cc399//mPJHSnnbgN5k/f/6aQ0NDwwMDA6VVq1aJHXwZGxtjUlhSnqxC&#10;YZnWlCxTDwwMuJB4PbGTySB2R2JsH8buCozVacr2n+3DiP1H3kBpwOkn39pQiZfLDfXX69fnY2uS&#10;+HpZhgMWFy9Z6s1DVxI2lLXbJzqSpJH+pLaUNWrvx6Fe2Kg9fUyLMdNxO3NFzOTkpOFPRMzExIQT&#10;ETEjIyPGHj9OKKce857+mN+UDQ4OxsxvmZEnUulHJD5EX5Lgt7F/HHs2cPYSX716tYsntW1cJjNs&#10;bVy/1HX1ReJxF6nkF+0zcw4bmFMiYvgjLSJu7rGesrYODti5JiWZNGXW9JKtNyRG1rb5zzZGXvjQ&#10;P/7+Xzf+8HuXX/OFaLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="1822"
height="2051"
viewBox="0 0 1822 2051"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="1822"
height="2051"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;AVAW7o8oLVradtIaKLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 157 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="1200"
height="1200"
viewBox="0 0 1200 1200"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="1200"
height="1200"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;sDKeB44QAgAAMMR+1Line truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 56 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="2048"
height="2048"
viewBox="0 0 2048 2048"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="2048"
height="2048"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;P1ADIgAAAIASEQAAALine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 86 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="169"
height="169"
viewBox="0 0 169 169"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="169"
height="169"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;8YQSBirhKengEMNtyLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 45 KiB

@@ -0,0 +1 @@
<svg width="1850" height="2500" viewBox="0 0 256 346" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><path d="M82.554 267.473s-13.198 7.675 9.393 10.272c27.369 3.122 41.356 2.675 71.517-3.034 0 0 7.93 4.972 19.003 9.279-67.611 28.977-153.019-1.679-99.913-16.517M74.292 229.659s-14.803 10.958 7.805 13.296c29.236 3.016 52.324 3.263 92.276-4.43 0 0 5.526 5.602 14.215 8.666-81.747 23.904-172.798 1.885-114.296-17.532" fill="#5382A1"/><path d="M143.942 165.515c16.66 19.18-4.377 36.44-4.377 36.44s42.301-21.837 22.874-49.183c-18.144-25.5-32.059-38.172 43.268-81.858 0 0-118.238 29.53-61.765 94.6" fill="#E76F00"/><path d="M233.364 295.442s9.767 8.047-10.757 14.273c-39.026 11.823-162.432 15.393-196.714.471-12.323-5.36 10.787-12.8 18.056-14.362 7.581-1.644 11.914-1.337 11.914-1.337-13.705-9.655-88.583 18.957-38.034 27.15 137.853 22.356 251.292-10.066 215.535-26.195M88.9 190.48s-62.771 14.91-22.228 20.323c17.118 2.292 51.243 1.774 83.03-.89 25.978-2.19 52.063-6.85 52.063-6.85s-9.16 3.923-15.787 8.448c-63.744 16.765-186.886 8.966-151.435-8.183 29.981-14.492 54.358-12.848 54.358-12.848M201.506 253.422c64.8-33.672 34.839-66.03 13.927-61.67-5.126 1.066-7.411 1.99-7.411 1.99s1.903-2.98 5.537-4.27c41.37-14.545 73.187 42.897-13.355 65.647 0 .001 1.003-.895 1.302-1.697" fill="#5382A1"/><path d="M162.439.371s35.887 35.9-34.037 91.101c-56.071 44.282-12.786 69.53-.023 98.377-32.73-29.53-56.75-55.526-40.635-79.72C111.395 74.612 176.918 57.393 162.439.37" fill="#E76F00"/><path d="M95.268 344.665c62.199 3.982 157.712-2.209 159.974-31.64 0 0-4.348 11.158-51.404 20.018-53.088 9.99-118.564 8.824-157.399 2.421.001 0 7.95 6.58 48.83 9.201" fill="#5382A1"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="973"
height="973"
viewBox="0 0 973 973"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="973"
height="973"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA80AAAPNCAYAAACztoj1AAAAinpUWHRSYXcgcHJvZmlsZSB0eXBl&#10;IGV4aWYAAHjadY7JDcUwCETvVJES2AymnMhJpN/BLz94kaIc8g7DgNAAnP/fBVuHUEGLVwszTDQ0&#10;eE9TcSKIxEi9pk5WFUrH2a4ehKexqI76LKriiyJW7XJ1t2LNGmc6nyJDSRzGVg/rr8QT1I7xR57+&#10;mC/gBgzMLa5HKQ0XAAAKBmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2lu&#10;PSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4&#10;PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhpdjIiPgogPHJkZjpS&#10;REYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMj&#10;Ij4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDov&#10;L25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUu&#10;Y29tL3RpZmYvMS4wLyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249Ijk3MyIKICAgZXhpZjpQaXhl&#10;bFlEaW1lbnNpb249Ijk3MyIKICAgdGlmZjpJbWFnZVdpZHRoPSI5NzMiCiAgIHRpZmY6SW1hZ2VI&#10;ZWlnaHQ9Ijk3MyIKICAgdGlmZjpPcmllbnRhdGlvbj0iMSIvPgogPC9yZGY6UkRGPgo8L3g6eG1w&#10;bWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;IAo8P3hwYWNrZXQgZW5kPSJ3Ij8+yNCSUQAAAARzQklUCAgICHwIZIgAACAASURBVHja7d27TiPZ&#10;g8DhM60OABFZxEg8CBEJISnEJAQ8AbGfgIDEsUkJSTrqB0EiRkQWdDYTjIo24Crf6nIu3yet5r+j&#10;1Wq3MIfz87nUP+9Ph/8GAAAA4JsfHgEAAACIZgAAABDNAAAAIJoBAABANAMAAIBoBgAAANEMAAAA&#10;ohkAAABEMwAAAIhmAAAAEM0AAAAgmgEAAADRDAAAAKIZAAAARDMAAACIZgAAABDNAAAAIJoBAABA&#10;NAMAAIBoBgAAANEMAAAAohkAAABEMwAAACCaAQAAQDQDAACAaAYAAADRDAAAAKIZAAAARDMAAACI&#10;ZgAAABDNAAAAIJoBAABANAMAAIBoBgAAAEQzAAAAiGYAAAAQzQAAACCaAQAAQDQDAACAaAYAAADR&#10;DAAAAKIZAAAARDMAAACIZgAAABDNAAAAgGgGAAAA0QwAAACiGQAAAEQzAAAAiGYAAAAQzQAAACCa&#10;AQAAQDQDAACAaAYAAADRDAAAAKIZAAAARDMAAAAgmgEAAEA0AwAAgGgGAAAA0QwAAACiGQAAAEQz&#10;AAAAiGYAAAAQzQAAACCaAQAAQDQDAACAaAYAAABEMwAAAIhmAAAAEM0AAAAgmgEAAEA0AwAAgGgG&#10;AAAA0QwAAACiGQAAAEQzAAAAiGYAAAAQzQAAAIBoBgAAANEMAAAAohkAAABEMwAAAIhmAAAAEM0A&#10;AAAgmgEAAEA0AwAAgGgGAAAA0QwAAACiGQAAABDNAAAAIJoBAABANAMAAIBoBgAAANEMAAAAohkA&#10;AABEMwAAAIhmAAAAEM0AAAAgmgEAAEA0AwAAAKIZAAAARDMAAACIZgAAABDNAAAAIJoBAABANAMA&#10;AIBoBgAAANEMAAAAohkAAABEMwAAAIhmAAAAEM0AAACAaAYAAADRDAAAAKIZAAAARDMAAACIZgAA&#10;ABDNAAAAIJoBAABANLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="2560"
height="1381"
viewBox="0 0 2560 1381"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="2560"
height="1381"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACgAAAAVlCAYAAADTJZXYAAAABGdBTUEAALGPC/xhBQAAACBjSFJN&#10;AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAA&#10;B3RJTUUH6AcBFggJlfFlVAAAgABJREFUeNrs3Xt8XPV95//394xkS77I+IolgwFjMIEGMPSWhN00&#10;XRpMsJu0Xdjekm2bLOkmDWlaEki626iP7m+D6XabbXqDdptLt21WxjayjB0Sp6ZbaJIW29hGNpdg&#10;ArYlW7eRZjT3c87n98dIviFbGklzfz0fjwTjOdKH85HmjGb0ns9HAgAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#10;AAAAAID65WgBAAAAAAAAaklHR/eCefOCRt93C4IGa7Qw0hzxvCZJkoWRMHAt48c6F7RIXkSSzIVN&#10;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&#10;7ZzLFUwrZq9rrW4JvLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 246 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="110"
height="110"
viewBox="0 0 110 110"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="110"
height="110"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;yeiNvwN+2IOhncBYXLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="2560"
height="1879"
viewBox="0 0 2560 1879"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="2560"
height="1879"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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&#10;rKdUBvr/R/wHAAAAALine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 109 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="301"
height="299"
viewBox="0 0 301 299"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="g1">
<image
width="301"
height="299"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS0AAAErCAYAAACLutXzAAAAi3pUWHRSYXcgcHJvZmlsZSB0eXBl&#10;IGV4aWYAAHjaXY7dDcIwDITfPQUj+C/neBworcQGjI/TRFTwPdh3lnU62t+vg24DYSdv0ZEAF56e&#10;ei/ReWLMoixj15ysbVJKyy5PplMge7Bfj+78QzN0HOERaNiwaaXrbnZOsaDza4SNKnkF6XMp+7s/&#10;vt1mkw8BKi1GGUDwKgAACgZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdp&#10;bj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6&#10;eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4KIDxyZGY6&#10;UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5z&#10;IyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOmV4aWY9Imh0dHA6&#10;Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2Jl&#10;LmNvbS90aWZmLzEuMC8iCiAgIGV4aWY6UGl4ZWxYRGltZW5zaW9uPSIzMDEiCiAgIGV4aWY6UGl4&#10;ZWxZRGltZW5zaW9uPSIyOTkiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMzAxIgogICB0aWZmOkltYWdl&#10;SGVpZ2h0PSIyOTkiCiAgIHRpZmY6T3JpZW50YXRpb249IjEiLz4KIDwvcmRmOlJERj4KPC94Onht&#10;cG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg&#10;ICAKPD94cGFja2V0IGVuZD0idyI/Po4mN3UAAAAEc0JJVAgICAh8CGSIAAAgAElEQVR42uy9aZRd&#10;13Um9u19zr1vqLkK8wwQIAmA8yxqoChKoiZK3dZSS5YdJV5x0llecezETq/E6XQS97CW7e7Vdsdt&#10;R9ZKbFly27Ikax45U5wnACSIgSDmAmqeXr3x3nP2zo9zX1WRlNuiALAKVfdbBIF6VfWGe8/5zh6/&#10;TcixbFFV7XWKYtIEy+jZkk6fL2DyVCdNHO+SmZFu9G243vukCJUIXkvwrsM718GkBcNaVJeWybU6&#10;4Jqd6pOCpkmXOB+JS2P1iVWfQL0H+RQKQEWgqlBVQBUMgJgBY0BsAGZ4U0psodyyNkqcAqKkxkat&#10;uKNjPC4UJ8VEjUSMJ7YVw5hS0gZATWO5yXFJYvLjUWfnq7R2V5V7NzQa5XUt6V3fMITUAmkH0Ux+&#10;55c3KL8Ely9UlVGf4WR2so9E+tNGLXbTowNJZXSVmzq3Oq1N3Uz1iXXarJo0QVkUZah0kSS9kjS7&#10;kDaL5Jqs4kEkIFIQFOIB7wCoggiAAoDCkwExQKrhT/gGYPmnLCed+0qJAAo/bSBgCt9VRfsZAK8Q&#10;VRATiEz4NxTGAAIDthawkUaFYouj8piHqdgoqiVOGuK1DlBi12ycIGOPmt5NY9q7ecx2rxnnck/d&#10;SzJiamOTPTd+QGJAiEjz1ZOTVo5LR0wWgAVQqB5+oCsdPrPFt5obNKl3M7AtqU1vdJXxK7Q6vlFq&#10;UxGpFJS4CKDgk1aJJAW8C9YPAOJAIAAgotA0Iw6mub8NKZgUqgQBBYIBwRoNhBMMKRAhWFb+zRxA&#10;hLnXaTOTqgLEEFWoKIgI1H4vUDBReCWV7FcJPvs5gCAi4YnYwHuBtQSogFTBTPBxCSaKPcg0RbRJ&#10;qk2KConp6h835Z6z1LXmrJZ6zpGJxqNS53Qcx4c7brhvLOrsbABwRJTkKy4nrRxvAQ1VU5+sbkyq&#10;M0UaP9aHU09u0eb0jLine truncated
id="image1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 56 KiB

+4
View File
@@ -0,0 +1,4 @@
#root {
margin: 0 auto;
width: 100%;
}
+19
View File
@@ -0,0 +1,19 @@
import './App.css'
import { Routes, Route } from 'react-router-dom';
import HomePage from './pages/Home/HomePage.jsx';
import ProjectsPage from './pages/Projects/ProjectsPage.jsx';
import ProjectDetailsPage from "./pages/ProjectDetails/ProjectDetailsPage.jsx";
function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/projects" element={<ProjectsPage />} />
<Route path="/projectDetails/:id" element={<ProjectDetailsPage />} />
</Routes>
)
}
export default App
@@ -0,0 +1,33 @@
.footer {
padding: 2rem 0;
margin-top: 4rem;
border-top: 1px solid #333;
color: var(--text-color);
font-size: 0.9rem;
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
width: 80%;
max-width: 1000px;
margin: 0 auto;
}
.footer-links {
display: flex;
gap: 1.5rem;
a{
display: flex;
align-items: center;
justify-content: center;
color: var(--text-color);
transition: color 0.3s ease, transform 0.3s ease;
}
}
.footer-links a:hover {
color: var(--title-color);
transform: translateY(-3px);
}
@@ -0,0 +1,28 @@
import './Footer.css';
function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer className="footer">
<div className="footer-content">
<div className="footer-copyright">
© {currentYear} • Giovanni Josserand
</div>
<div className="footer-links">
<a href="https://github.com/Giovanni-Josserand" target="_blank" rel="noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="24px" height="24px">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
</a>
<a href="https://gitea.josserand.ovh/Giovanni-Josserand" target="_blank" rel="noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="24px" height="24px">
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"/>
</svg>
</a>
</div>
</div>
</footer>
);
}
export default Footer;
@@ -0,0 +1,50 @@
.navbar {
position: fixed;
top: 30px;
background: rgba(100,100,100, 0.25);
backdrop-filter: blur(12px);
border-radius: 25px;
padding: 6px 10px;
z-index: 100;
border: solid rgba(100,100,100,0.5) 0.001rem;
}
.nav-list {
list-style: none;
display: flex;
gap: 1.3rem;
margin: 0;
padding: 0;
align-items: center;
li{
display: flex;
}
}
.nav-link {
text-decoration: none;
padding: 0.3rem 0.8rem;
border-radius: 20px;
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
cursor: pointer;
border: none;
background: none;
}
.nav-link:hover {
color: var(--important-color);
}
.nav-link.active {
background-color: rgba(217, 95, 70, 0.3);
color: var(--important-color);
}
@media (max-width: 768px) {
.nav-list{
gap: 0.5rem;
}
}
@@ -0,0 +1,89 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import "./NavBar.css";
const NavBar = () => {
const [active, setActive] = useState("home-section");
const [isScrolling, setIsScrolling] = useState(false);
const navigate = useNavigate();
useEffect(() => {
if (location.pathname === '/') {
const sections = document.querySelectorAll("section");
const navHeight = document.querySelector(".navbar")?.offsetHeight + 40 || 120;
const handleScroll = () => {
if (isScrolling) return;
let current = "home-section";
sections.forEach((section) => {
const sectionTop = section.offsetTop - navHeight;
if (window.scrollY >= sectionTop) {
current = section.id;
}
});
setActive(current);
};
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}
}, [isScrolling, location.pathname]);
const handleClick = (id) => {
if (location.pathname === '/') {
setActive(id);
setIsScrolling(true);
document.getElementById(id)?.scrollIntoView({ behavior: "smooth" });
setTimeout(() => setIsScrolling(false), 800);
} else {
navigate(`/#${id}`);
}
};
return (
<nav className="navbar">
<ul className="nav-list">
<li>
<button
onClick={() => handleClick("home-section")}
className={`nav-link ${active === "home-section" ? "active" : ""}`}
>
Home
</button>
</li>
<li>
<button
onClick={() => handleClick("experiences-section")}
className={`nav-link ${active === "experiences-section" ? "active" : ""}`}
>
Experiences
</button>
</li>
<li>
<button
onClick={() => handleClick("projects-section")}
className={`nav-link ${active === "projects-section" ? "active" : ""}`}
>
Projects
</button>
</li>
<li>
<button
onClick={() => handleClick("skills-section")}
className={`nav-link ${active === "skills-section" ? "active" : ""}`}
>
Skills
</button>
</li>
</ul>
</nav>
);
};
export default NavBar;
@@ -0,0 +1,62 @@
#projects-section{
display: flex;
flex-direction: column;
scroll-margin-top: 80px;
margin-top: 100px;
}
.show-more-container {
text-align: center;
}
.projects-link {
display: inline-block;
color: var(--text-color);
border: 1px solid var(--text-color);
background-color: transparent;
padding: 12px 28px;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
}
.projects-link:hover {
background-color: var(--text-color);
color: #1E1E1E;
transform: translateY(-3px);
cursor: pointer;
}
.projects-section-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.projects-section-header {
text-align: center;
margin-bottom: 2rem;
position: relative;
display: flex;
align-items: center;
flex-direction: column;
}
.projects-section-subtitle {
font-size: 1.2rem;
color: var(--title-color);
}
.projects-back-link {
text-align: center;
margin-bottom: 3rem;
}
@@ -0,0 +1,143 @@
import SingleProject from "../SingleProject/SingleProject.jsx";
import "./Projects.css"
import React, {useEffect, useState} from "react";
import {Link, useLocation} from "react-router-dom";
import NavBar from "../NavBar/NavBar.jsx";
import Filter from "../../pages/Projects/components/Filter/Filter.jsx";
function Projects() {
const [projects, setProjects] = useState([]);
const [error, setError] = useState(null);
const location = useLocation();
const [filters, setFilters] = useState({
category: [],
technology: [],
yearOrder: "asc",
});
useEffect(() => {
const fetchProjects = async () => {
try {
const response = await fetch('/api/projects/');
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
const data = await response.json();
setProjects(data);
} catch (err) {
setError(err.message);
}
};
fetchProjects();
}, []);
if (error) {
return <div>Error retrieving data: {error}</div>;
}
if (location.pathname === '/') {
return (
<section id="projects-section">
<h1 className="section-title">Projects</h1>
<div className="projects-section-list">
{projects
.filter(project => project.id <= 3)
.map(project => (
<SingleProject
image={project.image_name}
title={project.title}
description={project.short_description}
skills={project.skills}
id={project.id}
school={project.school}
beginningYear={project.beginning_year}
endYear={project.end_year}
/>
))}
</div>
<div className="show-more-container">
<Link to="/projects" className="projects-link">Show more</Link>
</div>
</section>
)
}else if (location.pathname === '/projects') {
return (
<section id="projects-section">
<div className="projects-section-header">
<NavBar />
<h1 className="section-title">All Projects</h1>
<p className="projects-section-subtitle">Here you can find a collection of my work.</p>
<Filter filters={filters} setFilters={setFilters} />
</div>
<div className="projects-section-list">
{projects
.filter(project => {
const categoryFilters = filters.category;
if (categoryFilters.length > 0) {
const isSchool = project.school === 1;
const isFilterSchool = categoryFilters.includes("school");
const isFilterPersonal = categoryFilters.includes("personal");
if ((isSchool && !isFilterSchool) || (!isSchool && !isFilterPersonal)) {
return false;
}
}
if (filters.technology.length > 0) {
const isSkill = filters.technology.every(tech => project.skills.some(skill => skill.name === tech));
if(!isSkill){
return false
}
}
return true;
})
.sort((a, b) => {
const aInProgress = !a.end_year;
const bInProgress = !b.end_year;
if (filters.yearOrder === "asc") {
const yearDiff = a.beginning_year - b.beginning_year;
if (yearDiff !== 0) return yearDiff;
if (!aInProgress && bInProgress) return -1;
if (aInProgress && !bInProgress) return 1;
return 0;
} else if (filters.yearOrder === "desc") {
const yearDiff = b.beginning_year - a.beginning_year;
if (yearDiff !== 0) return yearDiff;
if (aInProgress && !bInProgress) return -1;
if (!aInProgress && bInProgress) return 1;
return 0;
} else {
return 0;
}
})
.map(project => (
<SingleProject
image={project.image_name}
title={project.title}
description={project.short_description}
skills={project.skills}
id={project.id}
nbImage={project.nb_image}
school={project.school}
beginningYear={project.beginning_year}
endYear={project.end_year}
/>
))}
</div>
<div className="projects-back-link">
<Link to="/" className="projects-link">← Back to Home</Link>
</div>
</section>
)
}
}
export default Projects
@@ -0,0 +1,139 @@
.single-project {
display: flex;
flex-direction: column;
width: 29%;
margin: 2rem auto;
overflow: hidden;
transition: all 0.3s ease-in-out;
border-radius: 12px;
background-color: #1E1E1E;
}
.single-project:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
cursor: pointer;
}
.single-project-top {
position: relative;
flex-shrink: 0;
width: 100%;
display: flex;
justify-content: center;
align-items: start;
overflow: hidden;
height: 210px;
}
.single-project-top img {
width: 100%;
height: auto;
display: block;
transition: opacity 0.3s ease-in-out;
opacity: 1;
object-fit: cover;
}
.single-project-bottom {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 2rem 2rem 2rem 0;
align-items: flex-start;
height: 100%;
}
.single-project-bottom-header {
margin-bottom : 1em;
}
.single-project-title-wrapper{
display: flex;
margin-left: 2rem;
width: 100%;
}
.single-project-bottom-container {
margin-left: 2rem;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
}
.single-project-line {
border-radius: 38px;
min-width: 1.5rem;
height: 0.25rem;
margin-top: 1.25rem;
margin-right: 1rem;
}
.color-blue {
background-color: #2556ff;
}
.color-green {
background-color: #36a837;
}
.color-purple {
background-color: #a646d9;
}
.color-red {
background-color: #ff0000;
}
.color-yellow {
background-color: #ffd427;
}
.single-project-title {
font-size: 2rem;
color: var(--title-color);
margin-top: 0;
margin-bottom: 0;
display: flex;
align-items: center;
gap: 1rem;
}
.single-project-description {
color: var(--text-color);
margin-bottom: 1.5rem;
text-align: justify;
}
.single-project-skills-list {
display: flex;
flex-wrap: wrap;
list-style: none;
padding: 0;
margin: 0;
gap: 8px;
}
.single-project-years{
color : var(--text-color);
margin : 0;
margin-left : 2em;
font-weight: bold;
font-style: italic;
}
@media (max-width: 1366px) {
.single-project {
width: 47%;
}
}
@media (max-width: 768px) {
.single-project {
width: 90%;
}
}
@@ -0,0 +1,60 @@
import React, { useState, useEffect, useRef } from "react";
import SkillCard from "../SkillCard/SkillCard.jsx";
import "./SingleProject.css";
import {Link, useNavigate} from "react-router-dom";
function SingleProject({ image, title, description, skills, id, school, beginningYear, endYear }) {
const color = ["blue", "green", "purple", "red", "yellow"]
const navigate = useNavigate();
const clickProject = () => {
navigate(`/projectDetails/${id}`);
}
return (
<div className="single-project" onClick={clickProject}>
<div className="single-project-top">
<img src={`/assets/images/projects/${image}/${image}_1.png`} alt={image}/>
</div>
<div className="single-project-bottom">
<div className="single-project-bottom-header">
<div className="single-project-title-wrapper">
<div className={`single-project-line color-${color[(id-1)%color.length]}`}></div>
<h3 className="single-project-title">
{title}
{school ? (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="#D95F46" width="1em" height="1em">
<path d="M80 259.8L289.2 345.9C299 349.9 309.4 352 320 352C330.6 352 341 349.9 350.8 345.9L593.2 246.1C602.2 242.4 608 233.7 608 224C608 214.3 602.2 205.6 593.2 201.9L350.8 102.1C341 98.1 330.6 96 320 96C309.4 96 299 98.1 289.2 102.1L46.8 201.9C37.8 205.6 32 214.3 32 224L32 520C32 533.3 42.7 544 56 544C69.3 544 80 533.3 80 520L80 259.8zM128 331.5L128 448C128 501 214 544 320 544C426 544 512 501 512 448L512 331.4L369.1 390.3C353.5 396.7 336.9 400 320 400C303.1 400 286.5 396.7 270.9 390.3L128 331.4z"/>
</svg>
) : null}
</h3>
</div>
{endYear === null ? (
<p className="single-project-years">{beginningYear + ' – in progress'}</p>
) : beginningYear === endYear ? (
<p className="single-project-years">{beginningYear}</p>
) : (
<p className="single-project-years">{beginningYear + ' – ' + endYear}</p>
)}
</div>
<div className="single-project-bottom-container">
<p className="single-project-description" style={{ whiteSpace: "pre-line" }}>
{description}
</p>
<ul className="single-project-skills-list">
{skills.map((skill) => (
<li key={skill.id}>
<SkillCard text={skill.name} />
</li>
))}
</ul>
</div>
</div>
</div>
);
}
export default SingleProject;
@@ -0,0 +1,24 @@
.skill-card {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 0.5rem;
padding: 0.25rem 0.75rem;
font-size: 0.875rem;
width: fit-content;
white-space: nowrap;
flex-shrink: 0;
gap: 0.5rem;
background-color: #171717;
color: white;
border: solid rgba(100,100,100) 0.001rem;
height: 1.5rem;
margin: 0.5% 2%;
}
.skill-card img {
width: 1rem;
height: 1.125rem;
pointer-events: none;
}
@@ -0,0 +1,12 @@
import "./SkillCard.css";
function SkillCard({ text }) {
return (
<div className="skill-card">
<img src={`/assets/images/skills/${text}.svg`} alt={text} />
<p>{text}</p>
</div>
);
}
export default SkillCard;
@@ -0,0 +1,112 @@
.space-background {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 123vh;
background: radial-gradient(ellipse at center, #0a001f 0%, #000000 80%);
overflow: hidden;
z-index: -1;
}
.star {
position: absolute;
width: 2px;
height: 2px;
background: white;
border-radius: 50%;
opacity: 0.8;
animation: twinkle 3s infinite ease-in-out alternate;
filter: drop-shadow(0 0 2px white);
}
.planet {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 120vw;
height: 23vw;
max-height: 400px;
background: #0D0D0D;
border-radius: 60% 60% 0 0 / 100% 100% 0 0;
z-index: 1;
box-shadow:
0 -20px 60px 10px rgba(255, 255, 255, 0.35),
inset 0 20px 60px 10px rgba(255, 255, 255, 0.25);
}
.planet::after {
content: "";
position: absolute;
top: -3px;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 100%;
border-top: 2.5px solid white;
border-radius: 60% 60% 0 0 / 100% 100% 0 0;
mask-image: linear-gradient(to right, transparent 0%, white 40%, white 60%, transparent 100%);
pointer-events: none;
z-index: 2;
}
@keyframes twinkle {
0% { opacity: 0.3; transform: scale(0.8); }
100% { opacity: 1; transform: scale(1.2); }
}
.nebula {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
mix-blend-mode: screen;
animation: nebulaMove 15s ease-in-out infinite alternate;
}
.nebula1 {
width: 400px;
height: 400px;
background: radial-gradient(circle, #9b59b6 0%, transparent 70%);
top: 10%;
left: 15%;
animation-delay: 0s;
}
.nebula2 {
width: 600px;
height: 600px;
background: radial-gradient(circle, #8e44ad 0%, transparent 70%);
top: 50%;
left: 65%;
animation-delay: 5s;
}
.nebula3 {
width: 350px;
height: 350px;
background: radial-gradient(circle, #663399 0%, transparent 70%);
top: 75%;
left: 35%;
animation-delay: 10s;
}
@keyframes nebulaMove {
0% {
transform: translate(0, 0) scale(1);
opacity: 0.5;
}
100% {
transform: translate(20px, -20px) scale(1.05);
opacity: 0.6;
}
}
@media (max-width: 840px) {
.planet {
display: none;
}
}
@@ -0,0 +1,24 @@
import React from "react";
import "./Background.css";
export default function Background() {
return (
<div className="space-background">
{[...Array(100)].map((_, i) => (
<div
key={i}
className="star"
style={{
top: `${Math.random() * 100}%`,
left: `${Math.random() * 100}%`,
animationDelay: `${Math.random() * 5}s`,
}}
/>
))}
<div className="nebula nebula1"></div>
<div className="nebula nebula2"></div>
<div className="nebula nebula3"></div>
<div className="planet"></div>
</div>
);
}
+53
View File
@@ -0,0 +1,53 @@
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
font-weight: 400;
background-color: #0D0D0D;
--title-color: #EAEAEA;
--text-color: #7c7c7c;
--important-color: #D95F46;
}
html{
scroll-behavior: smooth;
}
body {
margin: 0;
display: flex;
place-items: center;
}
.section-title {
font-size: 2.5rem;
color: var(--title-color);
text-transform: uppercase;
letter-spacing: 0.15rem;
text-align: center;
margin-bottom: 3rem;
}
.section-title::after {
content: '';
display: block;
width: 60px;
height: 3px;
background-color: var(--important-color);
margin: 1rem auto 0;
border-radius: 2px;
}
h1{
font-size: 4rem;
color: white;
}
h2{
color : var(--title-color);
}
h3 {
margin: 0;
color: var(--title-color);
}
+13
View File
@@ -0,0 +1,13 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom';
createRoot(document.getElementById('root')).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
)
+34
View File
@@ -0,0 +1,34 @@
import {useEffect} from 'react';
import { useLocation } from 'react-router-dom';
import Home from './components/Home/Home.jsx';
import Experiences from './components/Experiences/Experiences.jsx';
import Projects from '../../components/Projects/Projects.jsx';
import Skills from './components/Skills/Skills.jsx';
import Footer from '../../components/Footer/Footer.jsx';
function HomePage() {
const location = useLocation();
useEffect(() => {
if (location.hash) {
const id = location.hash.replace('#', '');
const element = document.getElementById(id);
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth' });
}, 100);
}
}
}, [location]);
return (
<div>
<Home/>
<Experiences/>
<Projects/>
<Skills/>
<Footer/>
</div>
);
}
export default HomePage;
@@ -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,41 @@
import './Experiences.css';
import SingleExperience from '../SingleExperience/SingleExperience.jsx';
import React, {useEffect, useState} from "react";
function Experiences() {
const [experiences, setExperiences] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
const fetchExperiences = 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);
} catch (err) {
setError(err.message);
}
};
fetchExperiences();
}, []);
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}/>
))}
</div>
</section>
);
}
export default Experiences;
@@ -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;
}
}
@@ -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/josserand_giovanni_cv.pdf" target="_blank" className="btn">See my CV</a>
</section>
);
}
export default Home;
@@ -0,0 +1,99 @@
.experience-card {
position: relative;
width: 90%;
margin-bottom: 3rem;
padding: 1.5em;
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 }) {
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">
{experience.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);
} 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
@@ -0,0 +1,41 @@
import { useParams } from "react-router-dom";
import React, { useEffect, useState } from "react";
import ProjectDetails from "./components/ProjectDetails/ProjectDetails.jsx";
import Footer from "../../components/Footer/Footer.jsx";
function ProjectDetailsPage() {
const { id } = useParams();
const [project, setProject] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
const fetchProject = async () => {
try {
const response = await fetch(`/api/projects/${id}`);
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
const data = await response.json();
setProject(data);
} catch (err) {
setError(err.message);
}
};
fetchProject();
}, [id]);
if (error) {
return <p>Erreur : {error}</p>;
}
return (
<div>
<ProjectDetails project={project}/>
<Footer/>
</div>
);
}
export default ProjectDetailsPage;
@@ -0,0 +1,193 @@
.project-details {
display: flex;
width: 70%;
margin: 0 15% 0 15%;
gap: 4%;
flex-direction: column;
}
.nav-bar{
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
overflow: hidden;
height: 280px;
background-image: url("/apps/frontend/publicrontend/public/assets/images/projectDetailsHeadband.png");
background-size: cover;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 200px;
background: linear-gradient(to top, #0D0D0D 0%, rgba(26, 26, 26, 0) 100%);
}
}
.project-details-header{
width: 100%;
border-bottom: 2px solid #333;
}
.project-details-header h1{
color: var(--title-color);
display: flex;
align-items: center;
gap: 1rem;
margin: 0;
justify-content: space-between;
}
.project-details-container {
width: 92%;
color: var(--text-color);
display: flex;
padding: 0 4%;
gap: 5%;
}
.project-details-content {
width: 80%
}
.project-details-content h2 {
margin-top: 2rem;
color: var(--title-color);
border-left: 4px solid var(--important-color);
padding-left: 0.75rem;
}
.project-details-years {
color : var(--text-color);
margin : 0;
font-weight: bold;
font-style: italic;
}
.project-details-short-description{
color: var(--text-color);
}
.project-details-header ul{
display: flex;
list-style: none;
padding: 0;
gap: 1em;
flex-wrap: wrap;
}
aside {
width: 20%;
height: fit-content;
position: sticky;
top: 150px;
color: var(--text-color);
}
.aside-title {
font-weight: bold;
color: var(--title-color);
margin-bottom: 1rem;
font-size: 1.1em;
}
aside ul{
border-left: 2px solid #333;
list-style: none;
padding: 0 0 0 1em;
}
aside ul li {
margin-bottom: 0.25em;
}
aside ul li a {
text-decoration: none;
color: var(--text-color);
}
aside ul li a:hover {
color: var(--title-color)
}
.return-button{
position: absolute;
top: 2em;
left: 20px;
border: none;
background: none;
padding: 7px;
cursor: pointer;
z-index: 10;
transition: background-color 0.3s ease;
justify-content: center;
align-items: center;
border-radius: 50%;
width: 38px;
height: 38px;
}
.return-button:hover {
background: rgba(100,100,100, 0.5);
cursor: pointer;
}
.return-button svg {
color: var(--text-color);
transition: all 0.3s ease;
}
.return-button:hover svg {
color: var(--title-color);
}
.repo_link {
display: flex;
gap: 1.5rem;
svg{
display: flex;
align-items: center;
justify-content: center;
color: var(--text-color);
transition: color 0.3s ease, transform 0.3s ease;
}
}
.repo_link svg:hover {
color: var(--title-color);
}
.project-details-header-left{
display: flex;
align-items: center;
gap: 0.5em;
}
.project-details-image {
width: 100%;
margin-bottom: 2%;
}
@media (max-width: 480px) {
.return-button {
top: 7em;
}
aside {
display: none;
}
.project-details-content{
width: 100%;
}
}
@@ -0,0 +1,119 @@
import "./ProjectDetails.css"
import SkillCard from "../../../../components/SkillCard/SkillCard.jsx";
import React, {useEffect, useState} from "react";
import NavBar from "../../../../components/NavBar/NavBar.jsx";
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import {useNavigate} from "react-router-dom";
function ProjectDetails({project}) {
const [mdTitle, setMdTitle] = useState([]);
const navigate = useNavigate();
useEffect(() =>{
if (!project.long_description) return;
const matches = [...project.long_description.matchAll(/^## (?!#)(.+)$/gm)];
setMdTitle(matches.map(match => match[1].trim()));
}, [project.long_description])
const handleSummaryClick = (event, anchor) => {
event.preventDefault();
const element = document.getElementById(anchor);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
};
return (
<div>
<button className="return-button" onClick={() => navigate(-1)}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="currentColor">
<path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/>
</svg>
</button>
<div className="nav-bar">
<NavBar/>
</div>
<div className="project-details">
<div className="project-details-header">
<h1>
<div className="project-details-header-left">
{project.title}
{project.school ? (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="#D95F46" width="1em" height="1em">
<path d="M80 259.8L289.2 345.9C299 349.9 309.4 352 320 352C330.6 352 341 349.9 350.8 345.9L593.2 246.1C602.2 242.4 608 233.7 608 224C608 214.3 602.2 205.6 593.2 201.9L350.8 102.1C341 98.1 330.6 96 320 96C309.4 96 299 98.1 289.2 102.1L46.8 201.9C37.8 205.6 32 214.3 32 224L32 520C32 533.3 42.7 544 56 544C69.3 544 80 533.3 80 520L80 259.8zM128 331.5L128 448C128 501 214 544 320 544C426 544 512 501 512 448L512 331.4L369.1 390.3C353.5 396.7 336.9 400 320 400C303.1 400 286.5 396.7 270.9 390.3L128 331.4z"/>
</svg>
) : null}
</div>
{typeof project.repo_link === "string" && project.repo_link.length > 0 ? (
<a href={project.repo_link} className="repo_link">
{project.repo_link.includes("github") ? (
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em">
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"/>
</svg>
)}
</a>
) : null}
</h1>
{project.end_year === null ? (
<p className="project-details-years">{project.beginning_year + ' – in progress'}</p>
) : project.beginning_year === project.end_year ? (
<p className="project-details-years">{project.beginning_year}</p>
) : (
<p className="project-details-years">{project.beginning_year + ' – ' + project.end_year}</p>
)}
<p className="project-details-short-description">{project.short_description}</p>
<ul>
{project.skills && project.skills.map((skill) => (
<li>
<SkillCard text={skill.name} />
</li>
))}
</ul>
</div>
<div className="project-details-container">
<div className="project-details-content">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h2({node, ...props}) {
const id = String(props.children).toLowerCase().replace(/\s+/g, "-");
return <h2 id={id} {...props} />;
}
}}
>
{project.long_description}
</ReactMarkdown>
{[...Array(project.nb_image)].map((_, i) => (
<img src={`/assets/images/projects/${project.image_name}/${project.image_name}_${i+1}.png`} alt={project.image_name} className="project-details-image"/>
))}
</div>
<aside>
<ul>
{mdTitle.map(title => {
const anchor = title.toLowerCase().replace(/\s+/g, "-");
return (
<li key={anchor}>
<a href={`#${anchor}`} onClick={(e) => handleSummaryClick(e, anchor)}>
{title}
</a>
</li>
);
})}
</ul>
</aside>
</div>
</div>
</div>
);
}
export default ProjectDetails
@@ -0,0 +1,12 @@
import Projects from "../../components/Projects/Projects.jsx";
import Footer from "../../components/Footer/Footer.jsx";
function ProjectsPage() {
return (
<div>
<Projects/>
<Footer/>
</div>
);
}
export default ProjectsPage;
@@ -0,0 +1,134 @@
.filter-btn {
position: absolute;
top: 2em;
right: 20px;
border: none;
background: none;
padding: 14px;
cursor: pointer;
z-index: 10;
transition: background-color 0.3s ease;
}
.filter-btn svg {
color: var(--text-color);
transition: all 0.3s ease;
}
.filter-btn svg:hover {
color: var(--title-color);
transform: translateY(-2px);
}
.filter-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(5px);
z-index: 100;
}
.filter-sidebar {
position: fixed;
top: 0;
right: -100%;
width: 100%;
max-width: 350px;
height: 100%;
background: rgba(42, 42, 42, 0.5);
backdrop-filter: blur(15px);
border-left: solid rgba(100,100,100,0.5) 1px;
z-index: 101;
display: flex;
flex-direction: column;
transition: right 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.filter-sidebar.visible {
right: 0;
}
.filter-sidebar-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
border-bottom: 1px solid rgba(100, 100, 100, 0.5);
}
.close-filter-btn {
background: none;
border: none;
color: var(--text-color);
cursor: pointer;
padding: 5px;
display: flex;
align-items: center;
justify-content: center;
transition: color 0.3s ease;
}
.close-filter-btn:hover {
color: var(--title-color);
}
.filter-sidebar-content {
padding: 1.5rem;
overflow-y: auto;
}
.filter-sidebar-content h4 {
color: var(--text-color);
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 1px;
margin-top: 0;
margin-bottom: 1rem;
display: flex;
justify-content: start;
}
.filter-group {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-bottom: 2rem;
}
.filter-tag {
background-color: transparent;
border: 1px solid var(--text-color);
color: var(--text-color);
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
font-size: 0.9rem;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
}
.filter-tag:hover {
background-color: var(--text-color);
color: #1E1E1E;
transform: translateY(-2px);
}
.filter-tag.active {
background-color: rgba(217, 95, 70, 0.3);
color: var(--important-color);
border-color: var(--important-color);
}
@media (max-width: 480px) {
.filter-btn {
top: 5em;
right: 20px;
}
}
@@ -0,0 +1,154 @@
import './Filter.css';
import React, {useEffect, useState} from "react";
function Filter({ filters, setFilters }) {
const [isFilterVisible, setIsFilterVisible] = useState(false);
const showFilters = () => setIsFilterVisible(true);
const hideFilters = () => setIsFilterVisible(false);
const [skills, setSkills] = useState([]);
const [error, setError] = useState(null);
const handleCategoryFilter = (category) => {
setFilters(prev => {
const alreadySelected = prev.category.includes(category);
return {
...prev,
category: alreadySelected
? prev.category.filter(c => c !== category)
: [...prev.category, category],
};
});
};
const toggleTechnologyFilter = (tech) => {
setFilters(prev => {
const alreadySelected = prev.technology.includes(tech);
return {
...prev,
technology: alreadySelected
? prev.technology.filter(t => t !== tech)
: [...prev.technology, tech],
};
});
};
const setYearOrder = (order) => {
setFilters(prev => ({
...prev,
yearOrder: prev.yearOrder === order ? null : order
}));
};
const resetFilters = () => {
setFilters({
category: [],
technology: [],
yearOrder: filters.yearOrder,
});
};
useEffect(() => {
if (isFilterVisible) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
return () => {
document.body.style.overflow = '';
};
}, [isFilterVisible]);
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);
} catch (err) {
setError(err.message);
}
};
fetchSkills();
}, []);
if (error) {
return <div>Error retrieving data: {error}</div>;
}
return (
<div>
<button className="filter-btn" onClick={showFilters}>
<svg xmlns="http://www.w3.org/2000/svg" height="30" viewBox="0 -960 960 960" width="30" fill="currentColor">
<path d="M440-160q-17 0-28.5-11.5T400-200v-240L168-736q-15-20-4.5-42t36.5-22h560q26 0 36.5 22t-4.5 42L560-440v240q0 17-11.5 28.5T520-160h-80Zm40-308 198-252H282l198 252Zm0 0Z"/>
</svg>
</button>
{isFilterVisible ? <div className="filter-overlay" onClick={hideFilters}></div> : null}
<div className={`filter-sidebar ${isFilterVisible ? 'visible' : ''}`}>
<div className="filter-sidebar-header">
<h3>Filter Projects</h3>
<button className="close-filter-btn" onClick={hideFilters}>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor">
<path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/>
</svg>
</button>
</div>
<div className="filter-sidebar-content">
<div className="filter-group">
<button
className={`filter-tag ${filters.category.length === 0 && filters.technology.length === 0 ? "active" : ""}`}
onClick={resetFilters}
>All</button>
</div>
<h4>Category</h4>
<div className="filter-group">
<button
className={`filter-tag ${filters.category.includes("school") ? "active" : ""}`}
onClick={() => handleCategoryFilter("school")}
>School</button>
<button
className={`filter-tag ${filters.category.includes("personal") ? "active" : ""}`}
onClick={() => handleCategoryFilter("personal")}
>Personal</button>
</div>
<h4>Technology</h4>
<div className="filter-group">
{skills.map(skill => (
<button
className={`filter-tag ${filters.technology.includes(skill.name) ? "active" : ""}`}
onClick={() => toggleTechnologyFilter(skill.name)}
>{skill.name}</button>
))}
</div>
<h4>YEAR</h4>
<div className="filter-group">
<button
className={`filter-tag ${filters.yearOrder === "asc" ? "active" : ""}`}
onClick={() => setYearOrder("asc")}
>Ascending</button>
<button
className={`filter-tag ${filters.yearOrder === "desc" ? "active" : ""}`}
onClick={() => setYearOrder("desc")}
>Descending</button>
</div>
</div>
</div>
</div>
);
}
export default Filter;
+15
View File
@@ -0,0 +1,15 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
},
}
}
})