Files
Hotel-Booking/Frontend/src/components/rooms/RoomGallery.tsx
Iliyan Angelov 6f85b8cf17 updates
2025-11-21 01:20:51 +02:00

181 lines
4.9 KiB
TypeScript

import React, { useState } from 'react';
import { ChevronLeft, ChevronRight, X } from 'lucide-react';
interface RoomGalleryProps {
images: string[];
roomName: string;
}
const RoomGallery: React.FC<RoomGalleryProps> = ({
images,
roomName
}) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [isModalOpen, setIsModalOpen] = useState(false);
const safeImages = Array.isArray(images) && images.length > 0
? images
: ['/images/room-placeholder.jpg'];
const goToPrevious = () => {
setCurrentIndex((prev) =>
prev === 0 ? safeImages.length - 1 : prev - 1
);
};
const goToNext = () => {
setCurrentIndex((prev) =>
prev === safeImages.length - 1 ? 0 : prev + 1
);
};
const openModal = (index: number) => {
setCurrentIndex(index);
setIsModalOpen(true);
};
const closeModal = () => {
setIsModalOpen(false);
};
return (
<>
{}
<div className="grid grid-cols-4 gap-2 h-96">
{}
<div
className="col-span-4 md:col-span-3 relative
overflow-hidden rounded-lg cursor-pointer
group"
onClick={() => openModal(0)}
>
<img
src={safeImages[0]}
alt={`${roomName} - Main`}
className="w-full h-full object-cover
transition-transform duration-300
group-hover:scale-110"
/>
<div
className="absolute inset-0 bg-black
bg-opacity-0 group-hover:bg-opacity-20
transition-all duration-300
flex items-center justify-center"
>
<span
className="text-white font-medium
opacity-0 group-hover:opacity-100
transition-opacity"
>
View large image
</span>
</div>
</div>
{}
<div
className="hidden md:flex flex-col gap-2
col-span-1"
>
{safeImages.slice(1, 4).map((image, index) => (
<div
key={index + 1}
className="relative overflow-hidden
rounded-lg cursor-pointer group
flex-1"
onClick={() => openModal(index + 1)}
>
<img
src={image}
alt={`${roomName} - ${index + 2}`}
className="w-full h-full object-cover
transition-transform duration-300
group-hover:scale-110"
/>
{index === 2 && safeImages.length > 4 && (
<div
className="absolute inset-0 bg-black
bg-opacity-60 flex items-center
justify-center"
>
<span className="text-white font-semibold">
+{safeImages.length - 4} images
</span>
</div>
)}
</div>
))}
</div>
</div>
{}
{isModalOpen && (
<div
className="fixed inset-0 z-50 bg-black
bg-opacity-90 flex items-center
justify-center"
onClick={closeModal}
>
<button
onClick={closeModal}
className="absolute top-4 right-4
text-white hover:text-gray-300
transition-colors z-10"
aria-label="Close"
>
<X className="w-8 h-8" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
goToPrevious();
}}
className="absolute left-4 text-white
hover:text-gray-300 transition-colors
z-10"
aria-label="Previous image"
>
<ChevronLeft className="w-12 h-12" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
goToNext();
}}
className="absolute right-4 text-white
hover:text-gray-300 transition-colors
z-10"
aria-label="Next image"
>
<ChevronRight className="w-12 h-12" />
</button>
<div
className="max-w-6xl max-h-[90vh] relative"
onClick={(e) => e.stopPropagation()}
>
<img
src={safeImages[currentIndex]}
alt={`${roomName} - ${currentIndex + 1}`}
className="max-w-full max-h-[90vh]
object-contain"
/>
<div
className="absolute bottom-4 left-1/2
transform -translate-x-1/2
bg-black bg-opacity-50
text-white px-4 py-2 rounded-full"
>
{currentIndex + 1} / {safeImages.length}
</div>
</div>
</div>
)}
</>
);
};
export default RoomGallery;