diff --git a/package.json b/package.json
index 58742c0..2babf0f 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"@directus/sdk": "^13.0.2",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.2.17",
+ "@uidotdev/usehooks": "^2.4.1",
"astro": "^4.0.3",
"classnames": "^2.3.2",
"random-avatar-generator": "^2.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index aa109d6..6d65a4c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -16,6 +16,9 @@ dependencies:
'@types/react-dom':
specifier: ^18.2.17
version: 18.2.17
+ '@uidotdev/usehooks':
+ specifier: ^2.4.1
+ version: 2.4.1(react-dom@18.2.0)(react@18.2.0)
astro:
specifier: ^4.0.3
version: 4.0.3(sass@1.69.5)(typescript@5.1.3)
@@ -3138,6 +3141,17 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
+ /@uidotdev/usehooks@2.4.1(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ react: '>=18.0.0'
+ react-dom: '>=18.0.0'
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@ungap/structured-clone@1.2.0:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
diff --git a/src/components/ProgressButton.tsx b/src/components/ProgressButton.tsx
index e40e3e7..58eb661 100644
--- a/src/components/ProgressButton.tsx
+++ b/src/components/ProgressButton.tsx
@@ -7,6 +7,7 @@ type ProgessButtonProps = {
icon: string;
onClick: () => void;
active: boolean;
+ paused: boolean;
duration: number;
};
@@ -15,13 +16,14 @@ const ProgressButton = ({
icon,
onClick,
active,
+ paused,
duration,
}: ProgessButtonProps) => {
return (
@@ -33,7 +35,9 @@ const ProgressButton = ({
diff --git a/src/components/Video.tsx b/src/components/Video.tsx
index 05472a7..89a0778 100644
--- a/src/components/Video.tsx
+++ b/src/components/Video.tsx
@@ -4,13 +4,15 @@ import { useRef, useEffect, useMemo } from "react";
type Props = {
className?: string;
- handleLoadedMetadata?: (duration: number) => void;
video: string;
+ paused: boolean;
+ handleLoadedMetadata?: (duration: number) => void;
};
export default function Video({
className,
video,
+ paused,
handleLoadedMetadata,
}: Props) {
const videoRef = useRef(null);
@@ -19,6 +21,13 @@ export default function Video({
if (videoRef.current) videoRef.current.defaultMuted = true;
}, []);
+ useEffect(() => {
+ if (videoRef.current) {
+ if (paused) videoRef.current.pause();
+ else videoRef.current.play();
+ }
+ }, [paused]);
+
const key = useMemo(() => video, [video]);
return (
diff --git a/src/components/VideoPlayer.tsx b/src/components/VideoPlayer.tsx
index d8683a0..c5f0864 100644
--- a/src/components/VideoPlayer.tsx
+++ b/src/components/VideoPlayer.tsx
@@ -1,4 +1,5 @@
import { useEffect, useState } from "react";
+import { useIntersectionObserver } from "@uidotdev/usehooks";
import ProgressButton from "./ProgressButton";
import useMediaQuery from "../hooks/useMediaQuery";
import Video from "./Video";
@@ -16,10 +17,15 @@ type Props = {
buttonFirstVidLabel: string;
buttonSecondVidLabel: string;
buttonThirdVidLabel: string;
- }
-}
+ };
+};
const VideoPlayer = (props: Props) => {
+ const [ref, entry] = useIntersectionObserver({
+ threshold: 0.75,
+ rootMargin: "0px",
+ });
+
const [position, setPosition] = useState(0);
const theme = useMediaQuery("(prefers-color-scheme: dark)")
? "dark"
@@ -37,6 +43,7 @@ const VideoPlayer = (props: Props) => {
}, [isMobile]);
useEffect(() => {
+ if (!entry?.isIntersecting) return;
const interval = setInterval(() => {
setPosition((prevPosition) => {
if (!isMobile ? prevPosition === 8 : prevPosition === 2) {
@@ -48,106 +55,110 @@ const VideoPlayer = (props: Props) => {
}, duration);
return () => clearInterval(interval);
- }, [position, duration, isMobile]);
+ }, [position, duration, isMobile, entry?.isIntersecting]);
return (
-
-
-
setPosition(0)}
- active={!isMobile ? position <= 2 : position === 0}
- duration={!isMobile ? duration * 3 : duration}
- >
- {props.textContent.buttonCollab}
-
-
setPosition(3)}
- active={!isMobile ? position > 2 && position <= 5 : position === 1}
- duration={!isMobile ? duration * 3 : duration}
- >
- {props.textContent.buttonModerate}
-
-
setPosition(6)}
- active={!isMobile ? position > 5 && position <= 8 : position === 2}
- duration={!isMobile ? duration * 3 : duration}
- >
- {props.textContent.buttonCustomize}
-
-
-
- {!isMobile && (
-
- )}
-
-
-
- {isMobile && (
-
+
);
-}
+};
export default VideoPlayer;
diff --git a/src/views/Choices/Choices.astro b/src/views/Choices/Choices.astro
index ce30e00..a5134b6 100644
--- a/src/views/Choices/Choices.astro
+++ b/src/views/Choices/Choices.astro
@@ -3,13 +3,12 @@ import VideoPlayer from "../../components/VideoPlayer";
import getTranslatedContent from "../../utils/directus";
import "./Choices.scss";
-const {lang} = Astro.params;
+const { lang } = Astro.params;
const content = await getTranslatedContent("Choices_Section", lang!);
---
{content.header}
{content.text}
-
+
-
diff --git a/src/views/Feedback/Feedback.astro b/src/views/Feedback/Feedback.astro
index e267a5c..bfc5756 100644
--- a/src/views/Feedback/Feedback.astro
+++ b/src/views/Feedback/Feedback.astro
@@ -1,10 +1,10 @@
---
import FeedbackCarousel from "./FeedbackCarousel.tsx";
-import getTranslatedContent, {getContent} from "../../utils/directus";
+import getTranslatedContent, { getContent } from "../../utils/directus";
-const {lang} = Astro.params;
+const { lang } = Astro.params;
const content = await getTranslatedContent("Feedback_Section", lang!);
-const testimonials = await getContent("testimonials") as FeedbackItem[];
+const testimonials = (await getContent("testimonials")) as FeedbackItem[];
export type FeedbackItem = {
name: string;
@@ -16,8 +16,8 @@ export type FeedbackItem = {
---
- {content.header}
- {content.text}
+ {content.header}
+ {content.text}
diff --git a/src/views/Feedback/FeedbackCarousel.tsx b/src/views/Feedback/FeedbackCarousel.tsx
index afd9525..090df84 100644
--- a/src/views/Feedback/FeedbackCarousel.tsx
+++ b/src/views/Feedback/FeedbackCarousel.tsx
@@ -5,6 +5,7 @@ import useElementSize from "../../hooks/useElementSize";
import "./FeedbackCarousel.scss";
import { useInterval } from "../../hooks/useInterval";
import FeedbackCard from "./FeedbackCard";
+import { useIntersectionObserver } from "@uidotdev/usehooks";
type FeedbackCarouselProps = {
items: FeedbackItem[];
@@ -47,6 +48,11 @@ const FeedbackCarousel = ({ items }: FeedbackCarouselProps) => {
const itemsPerSlide = availableSpace > 4 ? 4 : availableSpace;
const [intervalDelay, setIntervalDelay] = useState(8000);
+ const [ref, entry] = useIntersectionObserver({
+ threshold: 0.75,
+ rootMargin: "0px",
+ });
+
const { carouselFragment, useListenToCustomEvent, slideToItem } =
useSpringCarousel({
draggingSlideTreshold: 16,
@@ -69,6 +75,7 @@ const FeedbackCarousel = ({ items }: FeedbackCarouselProps) => {
}, [items, itemsPerSlide]);
useInterval(() => {
+ if (!entry?.isIntersecting) return;
if (activeSlide === groupedFeedback.length - 1) slideTo(0);
else slideTo(activeSlide + 1);
}, intervalDelay);
@@ -86,7 +93,7 @@ const FeedbackCarousel = ({ items }: FeedbackCarouselProps) => {
};
return (
-
+
{groupedFeedback?.length && carouselFragment}
{groupedFeedback.map((_, index) => {