diff --git a/src/app/page.tsx b/src/app/page.tsx index 5a1be64..6a73340 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -36,6 +36,7 @@ import LabelCard from "@components/CardYear"; import ProjectsSection from "@components/ProjectsSection"; import { motion } from "framer-motion"; import { Video } from "../types/Video"; +import Reviews from "@components/Reviews"; // const VIDEOS = [ // "/videos/features/virtual_tour.mp4", @@ -680,6 +681,7 @@ export default function App() { +
Проекты diff --git a/src/components/Histories.tsx b/src/components/Histories.tsx index e2a9861..aa507d8 100644 --- a/src/components/Histories.tsx +++ b/src/components/Histories.tsx @@ -6,8 +6,7 @@ import { Transition } from "react-transition-group"; import { motion } from "framer-motion"; import { Video } from "../types/Video"; -const CARD_COUNT = 3; -const videos: Video[] = [ +const VIDEOS: Video[] = [ { id: "1", value: "/videos/histories/1.mp4", @@ -52,18 +51,19 @@ const Histories = () => { }); const [selectedVideo, setSelectedVideo] = useState(0); const [_document, setDocument] = useState(); + const [isVideoFinish, setIsVideoFinish] = useState(false); function handleOnLeftMove(): void { if (selectedVideo > 0) { setSelectedVideo((prev) => prev - 1); - setOffset((prev) => prev + 1); + // setOffset((prev) => prev + 1); } } function handleOnRightMove(): void { if (selectedVideo < 2) { setSelectedVideo((prev) => prev + 1); - setOffset((prev) => prev - 1); + // setOffset((prev) => prev - 1); } } @@ -71,7 +71,7 @@ const Histories = () => { setDocument(document); setVideoRefs((elRefs) => - Array.from({ length: CARD_COUNT }, (_, index) => index).map( + Array.from({ length: VIDEOS.length }, (_, index) => index).map( (_, i) => elRefs[i] || createRef() ) ); @@ -121,7 +121,7 @@ const Histories = () => { currentVideoRef.current.currentTime; setVideoProgress(progress); - if (progress === 100) { + if (97 <= progress) { clearInterval(interval); } }, 1000); @@ -130,12 +130,19 @@ const Histories = () => { }, [selectedVideo, videoRefs]); useEffect(() => { - if (100 - 3 < videoProgress) { - if (offset <= -1 * videoRefs.length + 1) { - setOffset(0); + if (100 - 5 < videoProgress) { + if (selectedVideo >= videoRefs.length - 1) { + // setOffset(0); + console.log("first"); setSelectedVideo(0); + setVideoProgress(0); + const currentVideoRef = videoRefs[selectedVideo]; + if (currentVideoRef && currentVideoRef.current) { + currentVideoRef.current.currentTime = 0; + } } else { - setOffset((prev) => prev - 1); + console.log("second"); + // setOffset((prev) => prev - 1); setSelectedVideo((prev) => prev + 1); } } @@ -157,7 +164,7 @@ const Histories = () => {

graff.estate

- {videos.map((item, index) => ( + {VIDEOS.map((item, index) => ( { transform: `translateX(${-selectedVideo * cardWidth}px)`, }} > - {videos.map((video, index) => ( + {VIDEOS.map((video, index) => (
{ - {videos.map((video, index) => ( + {VIDEOS.map((video, index) => (
{ + const [isViewportEntered, setIsViewportEntered] = useState(false); + + function handleViewportEnter() { + if (isViewportEntered) return; + setIsViewportEntered(true); + } + + const [offset, setOffset] = useState(0); + const [videoRefs, setVideoRefs] = useState< + React.RefObject[] + >([]); + const [videoProgress, setVideoProgress] = useState(0); + const [cardWidth, setCardWidth] = useState(0); + const handlers = useSwipeable({ + onSwipedLeft: handleOnRightMove, + onSwipedRight: handleOnLeftMove, + trackMouse: true, + }); + const [selectedVideo, setSelectedVideo] = useState(0); + const [_document, setDocument] = useState(); + + function handleOnLeftMove(): void { + if (selectedVideo > 0) { + setSelectedVideo((prev) => prev - 1); + setOffset((prev) => prev + 1); + } + } + + function handleOnRightMove(): void { + if (selectedVideo < 2) { + setSelectedVideo((prev) => prev + 1); + setOffset((prev) => prev - 1); + } + } + + useEffect(() => { + setDocument(document); + + setVideoRefs((elRefs) => + Array.from({ length: VIDEOS.length }, (_, index) => index).map( + (_, i) => elRefs[i] || createRef() + ) + ); + }, []); + + useEffect(() => { + if (!_document) return; + + const clientWidth = _document.children[0].clientWidth; + + if (clientWidth >= 1600) { + setCardWidth(420); + } else if (clientWidth >= 1280) { + setCardWidth(379); + } else if (clientWidth >= 640) { + setCardWidth(370); + } else { + setCardWidth(clientWidth - 16); + } + }, [_document]); + + useEffect(() => { + videoRefs.forEach((video, index) => { + if (!video.current) return; + if (index === selectedVideo) { + video.current.play(); + } else { + video.current.pause(); + } + }); + }, [videoRefs, selectedVideo, isViewportEntered]); + + useEffect(() => { + const currentVideoRef = videoRefs[selectedVideo]; + if (!currentVideoRef || !currentVideoRef.current) return; + + const progress = Math.round( + (100 / currentVideoRef.current.duration) * + currentVideoRef.current.currentTime + ); + setVideoProgress(progress); + + const interval = setInterval(() => { + if (!currentVideoRef || !currentVideoRef.current) return; + const progress = + (100 / currentVideoRef.current.duration) * + currentVideoRef.current.currentTime; + + setVideoProgress(progress); + if (progress === 100) { + clearInterval(interval); + } + }, 1000); + + return () => clearInterval(interval); + }, [selectedVideo, videoRefs]); + + useEffect(() => { + if (100 - 3 < videoProgress) { + if (offset <= -1 * videoRefs.length + 1) { + setOffset(0); + setSelectedVideo(0); + } else { + setOffset((prev) => prev - 1); + setSelectedVideo((prev) => prev + 1); + } + } + }, [videoProgress]); + + return ( + +
+
+
+
+

+

+ Отзывы +

+

клиентов

+

+ + {VIDEOS.map((item, index) => ( + + {(state) => ( +
+

+ {item.title} +

+

+ {item.desc} +

+
+ )} +
+ ))} +
+
+ + +
+
+
+
+
+
+ {VIDEOS.map((video, index) => ( +
+
+ ))} +
+
+
+
+

+ {VIDEOS[selectedVideo].title} +

+

+ {VIDEOS[selectedVideo].desc} +

+
+
+
+
+
+ {VIDEOS.map((video, index) => ( +
+ ))} +
+
+
+ + ); +}; + +export default Reviews;