141 lines
5.1 KiB
TypeScript
141 lines
5.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import Image from "next/image";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { X, ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
|
interface FleetGalleryProps {
|
|
images: string[];
|
|
}
|
|
|
|
export function FleetGallery({ images }: FleetGalleryProps) {
|
|
const [selectedImage, setSelectedImage] = useState<number | null>(null);
|
|
|
|
const nextImage = () => {
|
|
if (selectedImage !== null) {
|
|
setSelectedImage((selectedImage + 1) % images.length);
|
|
}
|
|
};
|
|
|
|
const prevImage = () => {
|
|
if (selectedImage !== null) {
|
|
setSelectedImage((selectedImage - 1 + images.length) % images.length);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section className="py-24 bg-background px-6 md:px-12">
|
|
<div className="max-w-7xl mx-auto">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
className="mb-12"
|
|
>
|
|
<span className="text-primary font-headline font-bold text-xs tracking-[0.3em] uppercase mb-2 block">
|
|
SAHADAN KARELER
|
|
</span>
|
|
<h2 className="text-4xl md:text-5xl font-black text-on-surface uppercase tracking-tighter leading-none">
|
|
FİLOMUZ <span className="text-primary">AKSİYONDA</span>
|
|
</h2>
|
|
</motion.div>
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
{images.map((src, index) => (
|
|
<motion.div
|
|
key={src}
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ delay: index * 0.1 }}
|
|
whileHover={{ scale: 0.98 }}
|
|
className="relative aspect-square cursor-pointer overflow-hidden group bg-surface-container-low"
|
|
onClick={() => setSelectedImage(index)}
|
|
>
|
|
<Image
|
|
src={src}
|
|
alt={`Fleet image ${index + 1}`}
|
|
fill
|
|
sizes="(max-width: 768px) 50vw, 25vw"
|
|
className="object-cover transition-transform duration-500 group-hover:scale-110 grayscale group-hover:grayscale-0"
|
|
/>
|
|
<div className="absolute inset-0 bg-primary/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
|
|
<div className="w-12 h-12 rounded-full bg-white/10 backdrop-blur-md flex items-center justify-center border border-white/20">
|
|
<div className="w-1 h-4 bg-white rounded-full"></div>
|
|
<div className="w-4 h-1 bg-white rounded-full absolute"></div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<AnimatePresence>
|
|
{selectedImage !== null && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
className="fixed inset-0 z-[100] flex items-center justify-center bg-black/95 backdrop-blur-sm p-4 md:p-12"
|
|
onClick={() => setSelectedImage(null)}
|
|
>
|
|
<motion.button
|
|
initial={{ opacity: 0, scale: 0.5 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
className="absolute top-8 right-8 text-white hover:text-primary transition-colors z-[110]"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setSelectedImage(null);
|
|
}}
|
|
>
|
|
<X size={40} strokeWidth={1} />
|
|
</motion.button>
|
|
|
|
<button
|
|
className="absolute left-4 md:left-8 text-white hover:text-primary transition-colors z-[110]"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
prevImage();
|
|
}}
|
|
>
|
|
<ChevronLeft size={60} strokeWidth={1} />
|
|
</button>
|
|
|
|
<button
|
|
className="absolute right-4 md:right-8 text-white hover:text-primary transition-colors z-[110]"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
nextImage();
|
|
}}
|
|
>
|
|
<ChevronRight size={60} strokeWidth={1} />
|
|
</button>
|
|
|
|
<motion.div
|
|
layoutId={images[selectedImage]}
|
|
className="relative w-full h-full flex items-center justify-center"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="relative w-full h-full max-w-5xl max-h-[80vh]">
|
|
<Image
|
|
src={images[selectedImage]}
|
|
alt="Full size fleet image"
|
|
fill
|
|
className="object-contain"
|
|
sizes="100vw"
|
|
priority
|
|
/>
|
|
</div>
|
|
</motion.div>
|
|
|
|
<div className="absolute bottom-10 left-1/2 -translate-x-1/2 text-white/50 font-label text-xs tracking-widest uppercase">
|
|
{selectedImage + 1} / {images.length}
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</section>
|
|
);
|
|
}
|