This commit is contained in:
2024-10-15 07:36:13 +02:00
parent 3ca5907b9a
commit 2c4848c5be
6 changed files with 163 additions and 147 deletions

View File

@@ -35,3 +35,4 @@ jobs:
port: ${{ secrets.SERVER_PORT }}
uploads: |
./dist => /var/www/modelec.club
delete: true

125
package-lock.json generated
View File

@@ -23,9 +23,9 @@
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.10.0",
"prettier": "^3.3.3",
"typescript": "^5.5.3",
"typescript-eslint": "^8.8.0",
"vite": "^5.4.1"
"typescript": "^5.6.3",
"typescript-eslint": "^8.8.1",
"vite": "^5.4.9"
}
},
"node_modules/@ampproject/remapping": {
@@ -985,7 +985,6 @@
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
@@ -999,7 +998,6 @@
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
@@ -1009,7 +1007,6 @@
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
@@ -1338,16 +1335,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz",
"integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
"integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/type-utils": "8.8.0",
"@typescript-eslint/utils": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/type-utils": "8.8.1",
"@typescript-eslint/utils": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -1371,15 +1368,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz",
"integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz",
"integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/typescript-estree": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1399,13 +1396,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz",
"integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz",
"integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0"
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1416,13 +1413,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz",
"integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz",
"integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "8.8.0",
"@typescript-eslint/utils": "8.8.0",
"@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/utils": "8.8.1",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -1440,9 +1437,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz",
"integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz",
"integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1453,13 +1450,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz",
"integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz",
"integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -1517,15 +1514,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz",
"integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz",
"integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/typescript-estree": "8.8.0"
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.8.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1539,12 +1536,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz",
"integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz",
"integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/types": "8.8.1",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -2218,7 +2215,6 @@
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
"dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
}
@@ -2836,8 +2832,7 @@
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
]
},
"node_modules/react": {
"version": "18.3.1",
@@ -2921,7 +2916,6 @@
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
@@ -2982,7 +2976,6 @@
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
@@ -3120,11 +3113,10 @@
}
},
"node_modules/typescript": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3134,14 +3126,14 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz",
"integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==",
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.1.tgz",
"integrity": "sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.8.0",
"@typescript-eslint/parser": "8.8.0",
"@typescript-eslint/utils": "8.8.0"
"@typescript-eslint/eslint-plugin": "8.8.1",
"@typescript-eslint/parser": "8.8.1",
"@typescript-eslint/utils": "8.8.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3198,11 +3190,10 @@
}
},
"node_modules/vite": {
"version": "5.4.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
"integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
"version": "5.4.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz",
"integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",

View File

@@ -25,8 +25,8 @@
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.10.0",
"prettier": "^3.3.3",
"typescript": "^5.5.3",
"typescript-eslint": "^8.8.0",
"vite": "^5.4.1"
"typescript": "^5.6.3",
"typescript-eslint": "^8.8.1",
"vite": "^5.4.9"
}
}

View File

@@ -1,92 +1,116 @@
import React from "react";
import { NavArrowLeft, NavArrowRight } from "iconoir-react";
import "./carousel.css";
import React from 'react';
import { NavArrowLeft, NavArrowRight } from 'iconoir-react';
import './carousel.css';
interface CarouselProps {
carousel: CarouselImageProps[];
carousel: CarouselImageProps[];
}
interface CarouselImageProps {
image: string;
title: string;
text: string;
link?: string;
alt?: string;
image: string;
title: string;
text: string;
link?: string;
alt?: string;
}
export const Carousel: React.FC<CarouselProps> = ({ carousel }) => {
const [currentIndex, setCurrentImage] = React.useState(0);
const [imagesSize, setImagesSize] = React.useState<number[]>([]);
const carouselSlider = React.useRef<HTMLDivElement>(null);
const [currentIndex, setCurrentImage] = React.useState(0);
const [imagesSize, setImagesSize] = React.useState<number[]>([]);
const carouselSlider = React.useRef<HTMLDivElement>(null);
const nextImage = () => {
setCurrentImage((currentIndex + 1) % carousel.length);
const nextImage = () => {
setCurrentImage((prevIndex) => (prevIndex + 1) % (carousel.length * 2));
};
const previousImage = () => {
setCurrentImage(
(prevIndex) =>
(prevIndex - 1 + carousel.length * 2) % (carousel.length * 2)
);
};
React.useEffect(() => {
const interval = setInterval(() => {
nextImage();
}, 3000);
if (carouselSlider.current) {
const translate = imagesSize.reduce(
(acc, size, index) => (index < currentIndex ? acc + size : acc),
0
);
const gap = 25; // TODO: Find a way to get this value (HARDCODED)
carouselSlider.current.style.transform = `translateX(-${translate + gap * currentIndex}px)`;
}
const previousImage = () => {
setCurrentImage((currentIndex - 1 + carousel.length) % carousel.length);
}
React.useEffect(() => {
const interval = setTimeout(() => {
nextImage();
}, 3000);
if (currentIndex >= carousel.length) {
setTimeout(() => {
setCurrentImage(0);
if (carouselSlider.current) {
const translate = imagesSize.reduce((acc, size, index) => index < currentIndex ? acc + size : acc, 0);
const gap = 25; // TODO: Find a way to get this value (HARDCODED)
carouselSlider.current.style.translate = `-${translate+gap*currentIndex}px`;
carouselSlider.current.style.transition = 'none';
carouselSlider.current.style.transform = 'translateX(0)';
}
return () => clearInterval(interval);
}, [currentIndex, imagesSize, carouselSlider]);
function handleImageLoad(i: number, event: React.SyntheticEvent<HTMLImageElement>) {
setImagesSize((old) => {
const newSizes = [...old];
newSizes[i] = (event.target as HTMLImageElement).clientWidth;
return newSizes;
});
}, 300);
} else {
if (carouselSlider.current) {
carouselSlider.current.style.transition = 'transform 0.3s ease';
}
}
return (
<div className={"carousel"}>
<div className={"carousel-wrapper"}>
<div className={"carousel-slider"} ref={carouselSlider}>
{
carousel.map((image, index) => (
<div key={index} className={'slide'}>
<img
key={index}
className={`slide-image ${index === currentIndex ? "active" : ""}`}
src={image.image}
alt={image.alt ?? "Image Carousel"}
onLoad={(e) => handleImageLoad(index, e)}
/>
<div className={'slide-content'}>
<h3 className={'slide-title'}>{image.title}</h3>
<p className={'slide-text'}>{image.text}</p>
</div>
</div>
))
}
</div>
</div>
<div className="carousel-bar">
<button className={"carousel-button button_left"} onClick={previousImage}><NavArrowLeft /></button>
{
carousel.map((_, index) => (
<button
key={index}
className={`carousel-dot ${index === currentIndex ? "dot_active" : ""}`}
onClick={() => setCurrentImage(index)}
/>
))
}
<button className={"carousel-button button_right"} onClick={nextImage}><NavArrowRight /></button>
return () => clearInterval(interval);
}, [currentIndex, imagesSize, carouselSlider]);
function handleImageLoad(
i: number,
event: React.SyntheticEvent<HTMLImageElement>
) {
setImagesSize((old) => {
const newSizes = [...old];
newSizes[i] = (event.target as HTMLImageElement).clientWidth;
return newSizes;
});
}
return (
<div className={'carousel'}>
<div className={'carousel-wrapper'}>
<div className={'carousel-slider'} ref={carouselSlider}>
{[...carousel, ...carousel].map((image, index) => (
<div key={index} className={'slide'}>
<img
key={index}
className={`slide-image ${index === currentIndex ? 'active' : ''}`}
src={image.image}
alt={image.alt ?? 'Image Carousel'}
onLoad={(e) => handleImageLoad(index, e)}
/>
<div className={'slide-content'}>
<h3 className={'slide-title'}>{image.title}</h3>
<p className={'slide-text'}>{image.text}</p>
</div>
</div>
))}
</div>
)
};
</div>
<div className="carousel-bar">
<button
className={'carousel-button button_left'}
onClick={previousImage}
>
<NavArrowLeft />
</button>
{carousel.map((_, index) => (
<button
key={index}
className={`carousel-dot ${index === currentIndex % carousel.length ? 'dot_active' : ''}`}
onClick={() => setCurrentImage(index)}
/>
))}
<button className={'carousel-button button_right'} onClick={nextImage}>
<NavArrowRight />
</button>
</div>
</div>
);
};

View File

@@ -1 +1 @@
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/carousel/carousel.tsx","./src/components/footer/footer.tsx","./src/components/middletext/middletext.tsx","./src/components/navbar/navbar.tsx","./src/components/navbarlink/navbarlink.tsx","./src/components/sidecard/fromleftcard.tsx","./src/components/sidecard/fromrightcard.tsx","./src/components/socialnetwork/socialnetwork.tsx","./src/components/team/team.tsx","./src/pages/404.tsx","./src/pages/home.tsx"],"version":"5.6.2"}
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/banner/banner.tsx","./src/components/box/box.tsx","./src/components/carousel/carousel.tsx","./src/components/contact/contact.tsx","./src/components/partner/partner.tsx","./src/components/projectcard/projectcard.tsx","./src/components/projetheader/projectheadercard.tsx","./src/components/projetheader/projetheader.tsx","./src/components/socialnetwork/socialnetwork.tsx","./src/components/team/team.tsx","./src/hooks/usewindowssize.tsx","./src/layouts/footer/footer.tsx","./src/layouts/navbar/navbar.tsx","./src/pages/404/404.tsx","./src/pages/contact/contact.tsx","./src/pages/home/home.tsx","./src/pages/partenaires/partenaires.tsx","./src/pages/projets/projets.tsx"],"version":"5.6.3"}

View File

@@ -1 +1 @@
{"root":["./vite.config.ts"],"version":"5.6.2"}
{"root":["./vite.config.ts"],"version":"5.6.3"}