Files
tech-fest/src/components/Activities.tsx
T

164 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* eslint-disable @next/next/no-img-element */
import { fluxgore } from "@/utils/fonts";
import { useRef, useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import type { Swiper as SwiperType } from "swiper";
import "swiper/css";
const iconPath = "/icons/swiper.svg";
function SwiperButton({
onClick,
direction = "next",
disabled = false,
}: {
onClick: () => void;
direction?: "next" | "prev";
disabled?: boolean;
}) {
return (
<button
onClick={onClick}
disabled={disabled}
className={`
w-10 h-10 sm:w-12 sm:h-12
border border-gray-200
transition-colors duration-200
flex items-center justify-center
${direction === "prev" ? "rotate-180" : ""}
${
disabled
? "bg-[#0e5a9c] cursor-not-allowed opacity-50"
: "bg-[#0e5a9c] hover:bg-[#0c4f87] active:bg-[#0a4373] hover:shadow-md"
}
`}
aria-label={direction === "next" ? "Next slide" : "Previous slide"}
>
<img src={iconPath} alt="" className={`w-4 h-4 sm:w-5 sm:h-5`} />
</button>
);
}
function Slide({ title, imageSrc }: { title: string; imageSrc: string }) {
return (
<div className="flex flex-col bg-[#1068B0] py-4 px-3 sm:py-6 sm:px-3.5 relative">
<h2 className={`${fluxgore.className} text-2xl sm:text-3xl lg:text-4xl text-white leading-none`}>
{title}
</h2>
<img
className="w-full h-auto object-cover mt-4 sm:mt-7"
src={imageSrc}
alt="Slide Image"
/>
<img
className="absolute top-full left-0 w-full h-auto object-cover"
src="/images/activities/paper_tear.png"
alt="Background Tear"
/>
</div>
);
}
function Activities() {
const swiperRef = useRef<SwiperType | null>(null);
const [isBeginning, setIsBeginning] = useState(true);
const [isEnd, setIsEnd] = useState(false);
const handlePrevious = () => {
swiperRef.current?.slidePrev();
};
const handleNext = () => {
swiperRef.current?.slideNext();
};
const handleSwiperInit = (swiper: SwiperType) => {
swiperRef.current = swiper;
setIsBeginning(swiper.isBeginning);
setIsEnd(swiper.isEnd);
};
const handleSlideChange = (swiper: SwiperType) => {
setIsBeginning(swiper.isBeginning);
setIsEnd(swiper.isEnd);
};
return (
<div className="bg-[#F4F4F4] relative pt-12 pb-16 sm:pt-16 sm:pb-24 lg:pt-20 lg:pb-32">
<div className="container mx-auto px-4">
<div className="flex space-y-6 flex-row sm:justify-between sm:items-center sm:space-y-0">
<h1
className={`${fluxgore.className} text-3xl sm:text-5xl lg:text-7xl text-[#060606] relative max-w-2xs md:max-w-full`}
>
Активности фестиваля
</h1>
<div className="flex items-center justify-center space-x-3 sm:space-x-5">
<SwiperButton
onClick={handlePrevious}
direction="prev"
disabled={isBeginning}
/>
<SwiperButton
onClick={handleNext}
direction="next"
disabled={isEnd}
/>
</div>
</div>
</div>
<div className="container mx-auto px-4 overflow-visible">
<div className="mt-8 sm:mt-12 lg:mt-16 overflow-visible">
<Swiper
spaceBetween={15}
slidesPerView={1}
onSwiper={handleSwiperInit}
onSlideChange={handleSlideChange}
watchOverflow={false}
className="!overflow-visible"
breakpoints={{
640: {
slidesPerView: 1,
spaceBetween: 15,
},
768: {
slidesPerView: 2,
spaceBetween: 20,
},
1024: {
slidesPerView: 3,
spaceBetween: 20,
},
}}
>
<SwiperSlide>
<Slide
title="Автовыставка"
imageSrc="/images/activities/car1.png"
/>
</SwiperSlide>
<SwiperSlide>
<Slide
title="дрифт такси"
imageSrc="/images/activities/taxi.png"
/>
</SwiperSlide>
<SwiperSlide>
<Slide
title="SMP Race такси"
imageSrc="/images/activities/race_taxi.png"
/>
</SwiperSlide>
</Swiper>
</div>
</div>
</div>
);
}
export default Activities;