clients page making
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 756 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 503 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 371 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 443 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,59 @@
|
||||
function chunkArray(arr: number[], cnt: number) {
|
||||
const resultArray = [];
|
||||
for (let i = 0; i < arr.length; i += cnt) {
|
||||
const chunk = arr.slice(i, i + cnt);
|
||||
resultArray.push(chunk);
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
const ClientsContainer = () => {
|
||||
const imageIndexes = Array.from({ length: 55 }, (_, i) => i + 1);
|
||||
const imageSections = chunkArray(imageIndexes, 4);
|
||||
|
||||
return (
|
||||
<div className="bg-white py-36">
|
||||
<div className="container xl:max-w-[1440px] mx-auto overflow-hidden">
|
||||
{imageSections.map((section, index) => {
|
||||
return (
|
||||
<div
|
||||
className="border-b grid grid-cols-4 last:border-b-0"
|
||||
key={index}
|
||||
>
|
||||
<div className="border-r p-5 last:border-r-0 flex items-center justify-center">
|
||||
<img
|
||||
src={`/images/clients/clients-${section[0]}.jpg`}
|
||||
alt=""
|
||||
className="w-[130px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="border-r p-5 last:border-r-0 flex items-center justify-center">
|
||||
<img
|
||||
src={`/images/clients/clients-${section[1]}.jpg`}
|
||||
alt=""
|
||||
className="w-[130px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="border-r p-5 last:border-r-0 flex items-center justify-center">
|
||||
<img
|
||||
src={`/images/clients/clients-${section[2]}.jpg`}
|
||||
alt=""
|
||||
className="w-[130px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="border-r p-5 last:border-r-0 flex items-center justify-center">
|
||||
<img
|
||||
src={`/images/clients/clients-${section[3]}.jpg`}
|
||||
alt=""
|
||||
className="w-[130px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClientsContainer;
|
||||
@@ -0,0 +1,110 @@
|
||||
import { useState } from "react";
|
||||
import ArrowCarouselIcon from "../../icons/ArrowCarouselIcon";
|
||||
import { thanksgivingLetters } from "../../consts/clientsPage";
|
||||
import { Image } from "../../types";
|
||||
import useStore from "../../store/store";
|
||||
import ZoomInLetterModal from "./ZoomInLetterModal";
|
||||
|
||||
const IMAGE_WIDTH = 660;
|
||||
|
||||
const ClientsPageCarousel = () => {
|
||||
const middleLetter = Math.floor(thanksgivingLetters.length / 2);
|
||||
const isOddCount = middleLetter % 2 === 1;
|
||||
const defaultOffset = isOddCount ? 300 : 0;
|
||||
|
||||
const { setModal } = useStore();
|
||||
const [letters, setLetters] = useState<Image[]>(thanksgivingLetters);
|
||||
const [currentImage, setCurrentImage] = useState(middleLetter);
|
||||
const [offset, setOffset] = useState(IMAGE_WIDTH);
|
||||
|
||||
const handleOnRightButtonClick = () => {
|
||||
if (currentImage < letters.length) {
|
||||
setOffset((prev) => prev - IMAGE_WIDTH);
|
||||
setCurrentImage((prev) => prev + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnLeftButtonClick = () => {
|
||||
if (currentImage > 1) {
|
||||
setOffset((prev) => prev + IMAGE_WIDTH);
|
||||
setCurrentImage((prev) => prev - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnBulletClick = (letterId: number) => {
|
||||
return () => {
|
||||
const updatedOffset = (currentImage - letterId) * IMAGE_WIDTH;
|
||||
setOffset((prev) => prev + updatedOffset);
|
||||
setCurrentImage(letterId);
|
||||
};
|
||||
};
|
||||
|
||||
const handleOnZoomIn = () => {
|
||||
setModal(
|
||||
<ZoomInLetterModal images={letters} currentImage={currentImage} />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white pb-4">
|
||||
<h1 className="font-bold text-[67px] text-center">
|
||||
Благодарственные письма
|
||||
</h1>
|
||||
<div className="py-24">
|
||||
<div className="flex h-[450px] w-[calc(100vw-20px)] overflow-hidden relative">
|
||||
<div
|
||||
className="flex transition-all duration-500 justify-center w-full "
|
||||
style={{
|
||||
transform: `translateX(${offset - defaultOffset}px)`,
|
||||
}}
|
||||
>
|
||||
{letters.map((letter) => (
|
||||
<div
|
||||
onClick={handleOnZoomIn}
|
||||
className={`transition-opacity duration-300 h-full min-w-[660px] flex justify-center ${
|
||||
letter.id !== currentImage
|
||||
? "opacity-30 pointer-events-none"
|
||||
: "cursor-zoom-in"
|
||||
}`}
|
||||
key={letter.id}
|
||||
>
|
||||
<img src={letter.image} alt="" className="max-h-full" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="absolute left-1/4 top-1/3 bg-[#e8e8e8] w-10 h-10 rounded-full"
|
||||
onClick={handleOnLeftButtonClick}
|
||||
>
|
||||
<ArrowCarouselIcon isLeft className="w-3 h-4 m-auto" />{" "}
|
||||
</button>
|
||||
<button
|
||||
className="absolute right-1/4 top-1/3 bg-[#e8e8e8] w-10 h-10 rounded-full"
|
||||
onClick={handleOnRightButtonClick}
|
||||
>
|
||||
<ArrowCarouselIcon className="w-[10px] h-4 m-auto" />{" "}
|
||||
</button>
|
||||
</div>
|
||||
<div className="mx-auto flex w-fit pt-6">
|
||||
{letters.map((letter) => (
|
||||
<div
|
||||
key={letter.id}
|
||||
className="cursor-pointer py-[10px] px-[5px] group"
|
||||
onClick={handleOnBulletClick(letter.id)}
|
||||
>
|
||||
<div
|
||||
key={letter.id}
|
||||
className={`w-2 h-2 rounded-full group-hover:bg-black transition-all duration-300 ${
|
||||
letter.id === currentImage ? "bg-black" : "bg-[#c7c7c7]"
|
||||
}`}
|
||||
></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClientsPageCarousel;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Image } from "../../types";
|
||||
|
||||
type ZoomInLetterModalProps = {
|
||||
images: Image[];
|
||||
currentImage: number;
|
||||
};
|
||||
|
||||
const ZoomInLetterModal = ({
|
||||
images,
|
||||
currentImage,
|
||||
}: ZoomInLetterModalProps) => {
|
||||
return (
|
||||
<div
|
||||
className="fixed w-screen h-screen bg-[#fff] z-30 flex justify-center items-center"
|
||||
// onClick={handleOnCloseClick}
|
||||
>
|
||||
<div
|
||||
className="flex"
|
||||
style={{
|
||||
transform: `translateX(calc(${-1 * currentImage}*000vw))`,
|
||||
}}
|
||||
>
|
||||
{images.map((image) => {
|
||||
return (
|
||||
<div key={image.id} className="h-screen w-screen">
|
||||
<img
|
||||
key={image.id}
|
||||
src={image.image}
|
||||
alt=""
|
||||
className="h-full mx-auto"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ZoomInLetterModal;
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ProjectType } from "../../types";
|
||||
import ProjectsSection from "./ProjectsSection";
|
||||
import { projects } from "../../consts/galleryPage";
|
||||
import { projects as mockProjects } from "../../consts/galleryPage";
|
||||
import useStore from "../../store/store";
|
||||
import { projectTabs } from "../../consts/galleryPage";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function getSlicedProjects(projects: ProjectType[]) {
|
||||
const chunkSize = 5;
|
||||
@@ -15,10 +18,25 @@ function getSlicedProjects(projects: ProjectType[]) {
|
||||
}
|
||||
|
||||
const ProjectsContainer = () => {
|
||||
const { selectedTab } = useStore();
|
||||
const [projects, setProjects] = useState(mockProjects);
|
||||
useEffect(() => {
|
||||
if (selectedTab.id === projectTabs[0].id) {
|
||||
setProjects(mockProjects);
|
||||
} else {
|
||||
const filteredProjects = mockProjects.filter((project) =>
|
||||
project.tabs.some((tab) => tab.id === selectedTab.id)
|
||||
);
|
||||
setProjects(filteredProjects);
|
||||
}
|
||||
|
||||
return () => {};
|
||||
}, [selectedTab]);
|
||||
|
||||
const slicedProjects = getSlicedProjects(projects);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-5">
|
||||
<div className="flex flex-col gap-5 pb-32">
|
||||
{slicedProjects.map((pr) => (
|
||||
<ProjectsSection projects={pr} />
|
||||
))}
|
||||
|
||||
@@ -33,6 +33,7 @@ const FiveProjects = ({ projects }: GalleryProjectsProps) => {
|
||||
const row = rows[index];
|
||||
return (
|
||||
<div
|
||||
key={el.id}
|
||||
className={`${row} relative h-full overflow-hidden after:absolute after:content-[''] after:z-10 after:w-full after:h-full after:top-0 after:left-0 after:bg-gradient-to-b after:from-[rgba(0,0,0,0)] after:to-[rgba(0,0,0,0.9)] cursor-pointer group`}
|
||||
>
|
||||
<img
|
||||
@@ -65,6 +66,7 @@ const FourProjects = ({ projects }: GalleryProjectsProps) => {
|
||||
const row = rows[index];
|
||||
return (
|
||||
<div
|
||||
key={el.id}
|
||||
className={`${row} relative h-full overflow-hidden after:absolute after:content-[''] after:z-10 after:w-full after:h-full after:top-0 after:left-0 after:bg-gradient-to-b after:from-[rgba(0,0,0,0)] after:to-[rgba(0,0,0,0.9)] cursor-pointer group`}
|
||||
>
|
||||
<img
|
||||
@@ -98,6 +100,7 @@ const ThreeProjects = ({ projects }: GalleryProjectsProps) => {
|
||||
const row = rows[index];
|
||||
return (
|
||||
<div
|
||||
key={el.id}
|
||||
className={`${row} relative h-full overflow-hidden after:absolute after:content-[''] after:z-10 after:w-full after:h-full after:top-0 after:left-0 after:bg-gradient-to-b after:from-[rgba(0,0,0,0)] after:to-[rgba(0,0,0,0.9)] cursor-pointer group`}
|
||||
>
|
||||
<img
|
||||
|
||||
@@ -7,7 +7,7 @@ const HeaderTitle = ({ title, description }: HeaderTitleProps) => {
|
||||
return (
|
||||
<section className="text-white mx-auto w-[1440px] flex flex-col pb-8 gap-8">
|
||||
<h2 className="text-6xl font-bold">{title}</h2>
|
||||
<p className="w-[39%]">{description}</p>
|
||||
<p className="text-2xl">{description}</p>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
||||
import ScrollToTopIcon from "../icons/ScrollToTopIcon";
|
||||
|
||||
const ScrollToTopButton = () => {
|
||||
const [isVisible, setIsVisible] = useState<boolean>(true);
|
||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleOnScroll = () => {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Image } from "../types";
|
||||
|
||||
const thanksgivingLetters: Image[] = [
|
||||
{ id: 1, image: "/images/clientsCarousel/clients-cal-1.jpg" },
|
||||
{ id: 2, image: "/images/clientsCarousel/clients-cal-2.jpg" },
|
||||
{ id: 3, image: "/images/clientsCarousel/clients-cal-3.jpg" },
|
||||
{ id: 4, image: "/images/clientsCarousel/clients-cal-4.jpg" },
|
||||
{ id: 5, image: "/images/clientsCarousel/clients-cal-5.jpg" },
|
||||
{ id: 6, image: "/images/clientsCarousel/clients-cal-6.jpg" },
|
||||
{ id: 7, image: "/images/clientsCarousel/clients-cal-7.jpg" },
|
||||
{ id: 8, image: "/images/clientsCarousel/clients-cal-8.jpg" },
|
||||
{ id: 9, image: "/images/clientsCarousel/clients-cal-9.jpg" },
|
||||
{ id: 10, image: "/images/clientsCarousel/clients-cal-10.jpg" },
|
||||
{ id: 11, image: "/images/clientsCarousel/clients-cal-11.jpg" },
|
||||
{ id: 12, image: "/images/clientsCarousel/clients-cal-12.jpg" },
|
||||
{ id: 13, image: "/images/clientsCarousel/clients-cal-13.jpg" },
|
||||
{ id: 14, image: "/images/clientsCarousel/clients-cal-14.jpg" },
|
||||
{ id: 15, image: "/images/clientsCarousel/clients-cal-15.jpg" },
|
||||
{ id: 16, image: "/images/clientsCarousel/clients-cal-16.jpg" },
|
||||
{ id: 17, image: "/images/clientsCarousel/clients-cal-17.jpg" },
|
||||
{ id: 18, image: "/images/clientsCarousel/clients-cal-18.jpg" },
|
||||
{ id: 19, image: "/images/clientsCarousel/clients-cal-19.jpg" },
|
||||
{ id: 20, image: "/images/clientsCarousel/clients-cal-20.jpg" },
|
||||
{ id: 21, image: "/images/clientsCarousel/clients-cal-21.jpg" },
|
||||
];
|
||||
|
||||
export { thanksgivingLetters };
|
||||
@@ -17,7 +17,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-1.jpg",
|
||||
description: "",
|
||||
link: "",
|
||||
tab:projectTabs[0]
|
||||
tabs:[projectTabs[0]]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@@ -25,7 +25,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-2.jpg",
|
||||
description: "Интерактивная презентация 2023.",
|
||||
link: "",
|
||||
tab:projectTabs[6]
|
||||
tabs:[projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
@@ -33,7 +33,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-3.jpg",
|
||||
description: "",
|
||||
link: "",
|
||||
tab:projectTabs[0]
|
||||
tabs:[projectTabs[0], projectTabs[4], projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
@@ -41,7 +41,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-4.jpg",
|
||||
description: "Интерактивная презентация жилого проекта 2023г.",
|
||||
link: "",
|
||||
tab:projectTabs[6]
|
||||
tabs:[projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
@@ -49,13 +49,15 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-5.jpg",
|
||||
description: "Строительный Форум100+ 2023г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: 'ЖК "Life Residence" для Паритет девелопмент',
|
||||
title: 'ЖК "Life Residence" для Паритет девелопмент г. Тюмень',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-6.jpg",
|
||||
description: "Интерактивная презентация 2023г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3], projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
@@ -63,13 +65,15 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-7.jpg",
|
||||
description: "Web Gl 2022г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[4]]
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: 'Центральная ППК"',
|
||||
title: 'АО "Центральная ППК"',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-8.jpg",
|
||||
description: "AR приложение 2022г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[2]]
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
@@ -77,6 +81,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-9.jpg",
|
||||
description: "Интерактивная 3D презентация 2022г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3]]
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
@@ -84,6 +89,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-10.jpg",
|
||||
description: "VR 2022г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[1]]
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
@@ -91,6 +97,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-11.jpg",
|
||||
description: "",
|
||||
link: "",
|
||||
tabs:[projectTabs[2], projectTabs[5]]
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
@@ -98,6 +105,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-12.jpg",
|
||||
description: "Интерактивный макет с VR - туром 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[1], projectTabs[3], projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
@@ -105,13 +113,15 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-13.jpg",
|
||||
description: "TOUCH-SCREEN 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[1], projectTabs[3], projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
title: 'ООО "CyberLympha" 2021г.',
|
||||
title: 'ООО "CyberLympha"',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-14.jpg",
|
||||
description: "Мобильная AR игра",
|
||||
description: "Мобильная AR игра 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[2], projectTabs[3], projectTabs[5]]
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
@@ -119,6 +129,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-15.jpg",
|
||||
description: "",
|
||||
link: "",
|
||||
tabs:[projectTabs[2], projectTabs[5]]
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
@@ -126,6 +137,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-16.jpg",
|
||||
description: "Интерактивный макет 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3], projectTabs[6]]
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
@@ -133,6 +145,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-17.jpg",
|
||||
description: "Виртуальная выставка 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[4]],
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
@@ -140,6 +153,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-18.jpg",
|
||||
description: "Интерактивная онлайн выставка 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[4]],
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
@@ -147,6 +161,7 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-19.jpg",
|
||||
description: "Интерактивная онлайн выставка 2020г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[4]],
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
@@ -154,6 +169,207 @@ const projectTabs: ProjectTab[] = [
|
||||
imagePath: "/images/galleryProjects/gallery-projects-20.jpg",
|
||||
description: "Интерактивный конфигуратор квартиры 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3], projectTabs[6]],
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
title: "Приложение для World Skills Russia МежВУЗ",
|
||||
imagePath: "/images/galleryProjects/gallery-projects-21.jpg",
|
||||
description: "Мобильное приложение 2021г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3], projectTabs[5]],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
title: "Вертолет КА-52",
|
||||
imagePath: "/images/galleryProjects/gallery-projects-22.jpg",
|
||||
description: "2020г.",
|
||||
link: "",
|
||||
tabs:[projectTabs[3]],
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
tabs:[projectTabs[0]],
|
||||
title: "Cимулятор погрузчика ричстакера SANY SRSC45C30",
|
||||
imagePath: "/images/galleryProjects/gallery-projects-23.jpg",
|
||||
description: "Интерактивное приложение - тренажёр 2020г.",
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
tabs:[projectTabs[1], projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "УРАЛЬСКИЙ" для ГК Эфес г. Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-24.jpg",
|
||||
description: 'Интерактивный макет 2020г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
tabs:[projectTabs[1]],
|
||||
title: 'Сборка- разборка вертолетного двигателя',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-25.jpg",
|
||||
description: 'Интерактивный VR тренажер 2020г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 26,
|
||||
tabs:[projectTabs[1], projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "Атмосфера" Фабрика Атмосферы г.Брянск',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-26.jpg",
|
||||
description: 'Интерактивная 3D презентация для продажи недвижимости 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 27,
|
||||
tabs:[projectTabs[1],projectTabs[3]],
|
||||
title: 'L 410 NG Aircraft',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-27.jpg",
|
||||
description: 'Интерактивная презентация самолёта 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'Самолет СУ-35',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-28.jpg",
|
||||
description: 'Интерактивная презентация 2020г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 29,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'Военнный корабль Удалой',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-29.jpg",
|
||||
description: 'Интерактивная презентация 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
tabs:[projectTabs[3], projectTabs[1]],
|
||||
title: 'Танковый двигатель В-2',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-30.jpg",
|
||||
description: 'Интерактивный VR тренажер 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'Военный автомобиль Тигр',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-31.jpg",
|
||||
description: 'Интерактивная презентация 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'АО "Уралхиммаш"',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-32.jpg",
|
||||
description: '3D презентация линии производства г.2019',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
tabs:[projectTabs[3], projectTabs[5], projectTabs[6]],
|
||||
title: 'ЖК "Рудный" г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-33.jpg",
|
||||
description: 'Мобильное приложение для продажи недвижимости 2017г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 34,
|
||||
tabs:[projectTabs[2], projectTabs[5], projectTabs[6]],
|
||||
title: 'ЖК "Солнечный" для ГК Брусника г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-34.jpg",
|
||||
description: 'AR дополненная реальность 2019г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 35,
|
||||
tabs:[projectTabs[3], projectTabs[5], projectTabs[6]],
|
||||
title: 'ЖК "Тринити" для АН "НКС" г. Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-35.jpg",
|
||||
description: 'Интерактивная 3д презентация для продажи недвижимости 2020г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 36,
|
||||
tabs:[projectTabs[3], projectTabs[5], projectTabs[6]],
|
||||
title: 'ЖК "Дом на Опалихинской" г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-36.jpg",
|
||||
description: 'Интерактивная 3D презентация для продажи недвижимости 2017г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 37,
|
||||
tabs:[projectTabs[1], projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "СВОЙ КРУГ" для Синара девелопмент г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-37.jpg",
|
||||
description: 'Интерактивная 3д презентация для продажи недвижимости 2016г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 38,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'МЦОД РФЯЦ-ВНИИТФ РОСАТОМ',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-38.jpg",
|
||||
description: 'Мультимедийная презентация 2018г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 39,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'ГК "ПИК- Индустрия" Презентация цеха мелкоштучных изделий',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-39.jpg",
|
||||
description: 'Интерактивная презентация 2017г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
tabs:[projectTabs[1],projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "Миллениум" г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-40.jpg",
|
||||
description: 'Интерактивная 3D презентация для продажи недвижимости 2018г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 41,
|
||||
tabs:[projectTabs[3]],
|
||||
title: 'Пирамида для РФЯЦ-ВНИИТФ РОCАТОМ',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-41.jpg",
|
||||
description: 'Интерактивная презентация с голографической пирамидой 2018г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
tabs:[projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "Электродом" КОРТРОС г. Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-42.jpg",
|
||||
description: 'Интерактивная 3D презентация для демонстрации системы рекуперации 2016г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 43,
|
||||
tabs:[projectTabs[3], projectTabs[6]],
|
||||
title: 'ЖК "Александровский" г.Екатеринбург',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-43.jpg",
|
||||
description: 'Интерактивная 3D презентация для продажи недвижимости 2015г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 44,
|
||||
tabs:[projectTabs[0]],
|
||||
title: '3D Интерактивная инструкция по сборке агрегата',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-44.jpg",
|
||||
description: '2015г.',
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
id: 45,
|
||||
tabs:[projectTabs[3], projectTabs[5]],
|
||||
title: 'Техноград ВДНХ',
|
||||
imagePath: "/images/galleryProjects/gallery-projects-45.jpg",
|
||||
description: '2017г.',
|
||||
link: "",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
type ArrowCarouselIconProps = {
|
||||
isLeft?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const ArrowCarouselIcon = ({ isLeft, className }: ArrowCarouselIconProps) => {
|
||||
return (
|
||||
<svg
|
||||
className={`w-6 h-6 ${className ? className : ""} ${
|
||||
isLeft ? "rotate-180" : ""
|
||||
}`}
|
||||
role="presentation"
|
||||
focusable="false"
|
||||
viewBox="0 0 9.3 17"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polyline
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
strokeLinecap="butt"
|
||||
strokeWidth="1"
|
||||
points="0.5,0.5 8.5,8.5 0.5,16.5"
|
||||
></polyline>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default ArrowCarouselIcon;
|
||||
@@ -18,10 +18,10 @@ const CrossCircleIcon = ({ isOpen }: CrossCircleIconProps) => {
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
stroke-width="1px"
|
||||
strokeWidth="1px"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="square"
|
||||
fillRule="evenodd"
|
||||
strokeLinecap="square"
|
||||
>
|
||||
<g transform="translate(1.000000, 1.000000)">
|
||||
<path d="M0,11 L22,11"></path>
|
||||
|
||||
@@ -8,7 +8,7 @@ const ScrollToTopIcon = () => {
|
||||
width="50px"
|
||||
height="50px"
|
||||
viewBox="0 0 48 48"
|
||||
enable-background="new 0 0 48 48"
|
||||
enableBackground="new 0 0 48 48"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
|
||||
@@ -6,6 +6,7 @@ import TechnologyPage from "./pages/TechnologyPage/TechnologyPage.tsx";
|
||||
import DirectionPage from "./pages/DirectionsPage/DirectionsPage.tsx";
|
||||
import "./index.css";
|
||||
import GalleryPage from "./pages/GalleryPage/GalleryPage.tsx";
|
||||
import ClientsPage from "./pages/ClientsPage/ClientsPage.tsx";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -28,6 +29,10 @@ const router = createBrowserRouter([
|
||||
path: "/gallery",
|
||||
element: <GalleryPage />,
|
||||
},
|
||||
{
|
||||
path: "/clients",
|
||||
element: <ClientsPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import HeaderTitle from "../../components/HeaderTitle";
|
||||
import ClientsContainer from "../../components/ClientsPage/ClientsContainer";
|
||||
import ClientsPageCarousel from "../../components/ClientsPage/ClientsPageCarousel";
|
||||
|
||||
const ClientsPage = () => {
|
||||
console.log("Array.from(5)");
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<HeaderTitle
|
||||
title={"Нам доверяют"}
|
||||
description='ООО "Граффинтерактив" работает на рынке IT- технологий более 18 лет.
|
||||
За это время нашими постоянными клиентами стало более 150 компаний и число постоянно увеличивается.'
|
||||
/>
|
||||
<ClientsContainer />
|
||||
<ClientsPageCarousel />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClientsPage;
|
||||
@@ -24,7 +24,7 @@ type ProjectType = {
|
||||
imagePath: string;
|
||||
description: string;
|
||||
link: string;
|
||||
tab?: ProjectTab;
|
||||
tabs: ProjectTab[];
|
||||
};
|
||||
|
||||
type ProjectTab = {
|
||||
@@ -32,4 +32,9 @@ type ProjectTab = {
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type {ProjectTab, AccordionType, AdvantageType, DirectionImageType, ProjectType}
|
||||
type Image = {
|
||||
id: number;
|
||||
image: string;
|
||||
}
|
||||
|
||||
export type {ProjectTab, AccordionType, AdvantageType, DirectionImageType, ProjectType, Image}
|
||||