461 lines
20 KiB
TypeScript
461 lines
20 KiB
TypeScript
|
|
import React, { useState } from 'react'
|
|||
|
|
import { motion, AnimatePresence } from 'framer-motion'
|
|||
|
|
import {
|
|||
|
|
HiHeart,
|
|||
|
|
HiChatBubbleLeft,
|
|||
|
|
HiMapPin,
|
|||
|
|
HiUsers,
|
|||
|
|
HiCalendar,
|
|||
|
|
HiXMark,
|
|||
|
|
HiChevronLeft,
|
|||
|
|
HiChevronRight
|
|||
|
|
} from 'react-icons/hi2'
|
|||
|
|
import dayjs from 'dayjs'
|
|||
|
|
import 'dayjs/locale/tr'
|
|||
|
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
|||
|
|
import { mockEvents, CalendarEvent, EventComment } from '../../../mocks/mockIntranetData'
|
|||
|
|
|
|||
|
|
dayjs.locale('tr')
|
|||
|
|
dayjs.extend(relativeTime)
|
|||
|
|
|
|||
|
|
const EventsModule: React.FC = () => {
|
|||
|
|
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(null)
|
|||
|
|
const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(0)
|
|||
|
|
const [showPhotoModal, setShowPhotoModal] = useState(false)
|
|||
|
|
const [selectedFilter, setSelectedFilter] = useState<'all' | 'social' | 'training' | 'company' | 'sport' | 'culture'>('all')
|
|||
|
|
const [newComment, setNewComment] = useState('')
|
|||
|
|
const [events, setEvents] = useState<CalendarEvent[]>(mockEvents)
|
|||
|
|
|
|||
|
|
const filteredEvents = selectedFilter === 'all'
|
|||
|
|
? events.filter(e => e.isPublished)
|
|||
|
|
: events.filter(e => e.isPublished && e.type === selectedFilter)
|
|||
|
|
|
|||
|
|
const handleLikeEvent = (eventId: string) => {
|
|||
|
|
setEvents(prev => prev.map(e =>
|
|||
|
|
e.id === eventId ? { ...e, likes: e.likes + 1 } : e
|
|||
|
|
))
|
|||
|
|
if (selectedEvent?.id === eventId) {
|
|||
|
|
setSelectedEvent(prev => prev ? { ...prev, likes: prev.likes + 1 } : null)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleAddComment = (eventId: string) => {
|
|||
|
|
if (!newComment.trim()) return
|
|||
|
|
|
|||
|
|
const comment: EventComment = {
|
|||
|
|
id: `c${Date.now()}`,
|
|||
|
|
author: {
|
|||
|
|
id: 'current-user',
|
|||
|
|
fullName: 'Sedat Öztürk',
|
|||
|
|
avatar: 'https://ui-avatars.com/api/?name=Sedat+Ozturk&background=3b82f6&color=fff'
|
|||
|
|
},
|
|||
|
|
content: newComment,
|
|||
|
|
createdAt: new Date(),
|
|||
|
|
likes: 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setEvents(prev => prev.map(e =>
|
|||
|
|
e.id === eventId ? { ...e, comments: [...e.comments, comment] } : e
|
|||
|
|
))
|
|||
|
|
|
|||
|
|
if (selectedEvent?.id === eventId) {
|
|||
|
|
setSelectedEvent(prev => prev ? { ...prev, comments: [...prev.comments, comment] } : null)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setNewComment('')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const getTypeColor = (type: string) => {
|
|||
|
|
const colors: Record<string, string> = {
|
|||
|
|
social: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300',
|
|||
|
|
training: 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300',
|
|||
|
|
company: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300',
|
|||
|
|
sport: 'bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-300',
|
|||
|
|
culture: 'bg-pink-100 dark:bg-pink-900/30 text-pink-700 dark:text-pink-300'
|
|||
|
|
}
|
|||
|
|
return colors[type] || colors.social
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const getTypeLabel = (type: string) => {
|
|||
|
|
const labels: Record<string, string> = {
|
|||
|
|
social: '🎉 Sosyal',
|
|||
|
|
training: '📚 Eğitim',
|
|||
|
|
company: '🏢 Kurumsal',
|
|||
|
|
sport: '⚽ Spor',
|
|||
|
|
culture: '🎨 Kültür'
|
|||
|
|
}
|
|||
|
|
return labels[type] || type
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 p-6">
|
|||
|
|
<div className="max-w-7xl mx-auto space-y-6">
|
|||
|
|
{/* Header */}
|
|||
|
|
<div>
|
|||
|
|
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
|
|||
|
|
🎊 Etkinlikler
|
|||
|
|
</h1>
|
|||
|
|
<p className="text-gray-600 dark:text-gray-400 mt-1">
|
|||
|
|
Şirket etkinlikleri, fotoğraflar ve anılar
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Filter Tabs */}
|
|||
|
|
<div className="flex gap-3 overflow-x-auto pb-2">
|
|||
|
|
{[
|
|||
|
|
{ value: 'all' as const, label: '🌟 Tümü' },
|
|||
|
|
{ value: 'social' as const, label: '🎉 Sosyal' },
|
|||
|
|
{ value: 'training' as const, label: '📚 Eğitim' },
|
|||
|
|
{ value: 'company' as const, label: '🏢 Kurumsal' },
|
|||
|
|
{ value: 'sport' as const, label: '⚽ Spor' },
|
|||
|
|
{ value: 'culture' as const, label: '🎨 Kültür' }
|
|||
|
|
].map((tab) => (
|
|||
|
|
<button
|
|||
|
|
key={tab.value}
|
|||
|
|
onClick={() => setSelectedFilter(tab.value)}
|
|||
|
|
className={`px-4 py-2 rounded-lg border-2 transition-all whitespace-nowrap ${
|
|||
|
|
selectedFilter === tab.value
|
|||
|
|
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
|
|||
|
|
: 'border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300'
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
{tab.label}
|
|||
|
|
</button>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Events Grid */}
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|||
|
|
{filteredEvents.map((event, idx) => (
|
|||
|
|
<motion.div
|
|||
|
|
key={event.id}
|
|||
|
|
initial={{ opacity: 0, y: 20 }}
|
|||
|
|
animate={{ opacity: 1, y: 0 }}
|
|||
|
|
transition={{ delay: idx * 0.1 }}
|
|||
|
|
className="bg-white dark:bg-gray-800 rounded-lg overflow-hidden border border-gray-200 dark:border-gray-700 hover:shadow-xl transition-all cursor-pointer"
|
|||
|
|
onClick={() => setSelectedEvent(event)}
|
|||
|
|
>
|
|||
|
|
{/* Cover Photo */}
|
|||
|
|
<div className="relative h-48 overflow-hidden">
|
|||
|
|
<img
|
|||
|
|
src={event.photos[0]}
|
|||
|
|
alt={event.title}
|
|||
|
|
className="w-full h-full object-cover hover:scale-110 transition-transform duration-300"
|
|||
|
|
/>
|
|||
|
|
<div className="absolute top-3 right-3">
|
|||
|
|
<span className={`px-3 py-1 rounded-full text-xs font-medium ${getTypeColor(event.type)}`}>
|
|||
|
|
{getTypeLabel(event.type)}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
{event.photos.length > 1 && (
|
|||
|
|
<div className="absolute bottom-3 right-3 bg-black/70 text-white px-2 py-1 rounded text-xs">
|
|||
|
|
+{event.photos.length - 1} fotoğraf
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Content */}
|
|||
|
|
<div className="p-4 space-y-3">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white line-clamp-2">
|
|||
|
|
{event.title}
|
|||
|
|
</h3>
|
|||
|
|
|
|||
|
|
<p className="text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
|
|||
|
|
{event.description}
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<div className="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
|
|||
|
|
<div className="flex items-center gap-1">
|
|||
|
|
<HiCalendar className="w-4 h-4" />
|
|||
|
|
{dayjs(event.date).format('DD MMMM YYYY')}
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-1">
|
|||
|
|
<HiMapPin className="w-4 h-4" />
|
|||
|
|
{event.location}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="flex items-center justify-between pt-3 border-t border-gray-200 dark:border-gray-700">
|
|||
|
|
<div className="flex items-center gap-4 text-sm">
|
|||
|
|
<button
|
|||
|
|
onClick={(e) => {
|
|||
|
|
e.stopPropagation()
|
|||
|
|
handleLikeEvent(event.id)
|
|||
|
|
}}
|
|||
|
|
className="flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-red-500 transition-colors"
|
|||
|
|
>
|
|||
|
|
<HiHeart className="w-5 h-5" />
|
|||
|
|
{event.likes}
|
|||
|
|
</button>
|
|||
|
|
<div className="flex items-center gap-1 text-gray-600 dark:text-gray-400">
|
|||
|
|
<HiChatBubbleLeft className="w-5 h-5" />
|
|||
|
|
{event.comments.length}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-1 text-sm text-gray-600 dark:text-gray-400">
|
|||
|
|
<HiUsers className="w-4 h-4" />
|
|||
|
|
{event.participants} kişi
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</motion.div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{filteredEvents.length === 0 && (
|
|||
|
|
<div className="text-center py-12 text-gray-500 dark:text-gray-400">
|
|||
|
|
<p className="text-lg">Bu kategoride henüz etkinlik yok</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Event Detail Modal */}
|
|||
|
|
<AnimatePresence>
|
|||
|
|
{selectedEvent && (
|
|||
|
|
<>
|
|||
|
|
<motion.div
|
|||
|
|
initial={{ opacity: 0 }}
|
|||
|
|
animate={{ opacity: 1 }}
|
|||
|
|
exit={{ opacity: 0 }}
|
|||
|
|
className="fixed inset-0 bg-black/50 z-40"
|
|||
|
|
onClick={() => setSelectedEvent(null)}
|
|||
|
|
/>
|
|||
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 overflow-y-auto">
|
|||
|
|
<motion.div
|
|||
|
|
initial={{ opacity: 0, scale: 0.95, y: 20 }}
|
|||
|
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|||
|
|
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
|||
|
|
className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto my-8"
|
|||
|
|
onClick={(e) => e.stopPropagation()}
|
|||
|
|
>
|
|||
|
|
{/* Header */}
|
|||
|
|
<div className="sticky top-0 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 p-6 z-10">
|
|||
|
|
<div className="flex items-start justify-between">
|
|||
|
|
<div className="flex-1">
|
|||
|
|
<div className="flex items-center gap-3 mb-2">
|
|||
|
|
<span className={`px-3 py-1 rounded-full text-xs font-medium ${getTypeColor(selectedEvent.type)}`}>
|
|||
|
|
{getTypeLabel(selectedEvent.type)}
|
|||
|
|
</span>
|
|||
|
|
<span className="text-sm text-gray-600 dark:text-gray-400">
|
|||
|
|
{dayjs(selectedEvent.date).format('DD MMMM YYYY')}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
|
|||
|
|
{selectedEvent.title}
|
|||
|
|
</h2>
|
|||
|
|
<p className="text-gray-600 dark:text-gray-400 mt-2">
|
|||
|
|
{selectedEvent.description}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<button
|
|||
|
|
onClick={() => setSelectedEvent(null)}
|
|||
|
|
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
|
|||
|
|
>
|
|||
|
|
<HiXMark className="w-6 h-6 text-gray-500" />
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="flex items-center gap-6 mt-4 text-sm text-gray-600 dark:text-gray-400">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<HiMapPin className="w-5 h-5" />
|
|||
|
|
{selectedEvent.location}
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<HiUsers className="w-5 h-5" />
|
|||
|
|
{selectedEvent.participants} katılımcı
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<img
|
|||
|
|
src={selectedEvent.organizer.avatar}
|
|||
|
|
alt={selectedEvent.organizer.fullName}
|
|||
|
|
className="w-6 h-6 rounded-full"
|
|||
|
|
/>
|
|||
|
|
<span>Düzenleyen: {selectedEvent.organizer.fullName}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Photo Gallery */}
|
|||
|
|
<div className="p-6">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
|
|||
|
|
📸 Fotoğraflar ({selectedEvent.photos.length})
|
|||
|
|
</h3>
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
|||
|
|
{selectedEvent.photos.map((photo, idx) => (
|
|||
|
|
<motion.div
|
|||
|
|
key={idx}
|
|||
|
|
whileHover={{ scale: 1.05 }}
|
|||
|
|
className="relative aspect-square rounded-lg overflow-hidden cursor-pointer"
|
|||
|
|
onClick={() => {
|
|||
|
|
setSelectedPhotoIndex(idx)
|
|||
|
|
setShowPhotoModal(true)
|
|||
|
|
}}
|
|||
|
|
>
|
|||
|
|
<img
|
|||
|
|
src={photo}
|
|||
|
|
alt={`${selectedEvent.title} - ${idx + 1}`}
|
|||
|
|
className="w-full h-full object-cover"
|
|||
|
|
/>
|
|||
|
|
</motion.div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Comments Section */}
|
|||
|
|
<div className="p-6 border-t border-gray-200 dark:border-gray-700">
|
|||
|
|
<div className="flex items-center justify-between mb-4">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
|
|||
|
|
💬 Yorumlar ({selectedEvent.comments.length})
|
|||
|
|
</h3>
|
|||
|
|
<div className="flex items-center gap-4 text-sm">
|
|||
|
|
<button
|
|||
|
|
onClick={() => handleLikeEvent(selectedEvent.id)}
|
|||
|
|
className="flex items-center gap-2 px-3 py-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 transition-colors"
|
|||
|
|
>
|
|||
|
|
<HiHeart className="w-5 h-5 text-red-500" />
|
|||
|
|
{selectedEvent.likes} beğeni
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Comments List */}
|
|||
|
|
<div className="space-y-4 mb-4">
|
|||
|
|
{selectedEvent.comments.map((comment) => (
|
|||
|
|
<div
|
|||
|
|
key={comment.id}
|
|||
|
|
className="flex gap-3 p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg"
|
|||
|
|
>
|
|||
|
|
<img
|
|||
|
|
src={comment.author.avatar}
|
|||
|
|
alt={comment.author.fullName}
|
|||
|
|
className="w-10 h-10 rounded-full"
|
|||
|
|
/>
|
|||
|
|
<div className="flex-1">
|
|||
|
|
<div className="flex items-center gap-2 mb-1">
|
|||
|
|
<span className="font-semibold text-gray-900 dark:text-white">
|
|||
|
|
{comment.author.fullName}
|
|||
|
|
</span>
|
|||
|
|
<span className="text-xs text-gray-500 dark:text-gray-400">
|
|||
|
|
{dayjs(comment.createdAt).fromNow()}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<p className="text-gray-700 dark:text-gray-300 text-sm">
|
|||
|
|
{comment.content}
|
|||
|
|
</p>
|
|||
|
|
<div className="flex items-center gap-2 mt-2">
|
|||
|
|
<button className="text-xs text-gray-500 hover:text-red-500 transition-colors">
|
|||
|
|
❤️ {comment.likes} beğeni
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Add Comment */}
|
|||
|
|
<div className="flex gap-3">
|
|||
|
|
<img
|
|||
|
|
src="https://ui-avatars.com/api/?name=Sedat+Ozturk&background=3b82f6&color=fff"
|
|||
|
|
alt="You"
|
|||
|
|
className="w-10 h-10 rounded-full"
|
|||
|
|
/>
|
|||
|
|
<div className="flex-1 flex gap-2">
|
|||
|
|
<input
|
|||
|
|
type="text"
|
|||
|
|
value={newComment}
|
|||
|
|
onChange={(e) => setNewComment(e.target.value)}
|
|||
|
|
onKeyPress={(e) => {
|
|||
|
|
if (e.key === 'Enter') {
|
|||
|
|
handleAddComment(selectedEvent.id)
|
|||
|
|
}
|
|||
|
|
}}
|
|||
|
|
placeholder="Yorumunuzu yazın..."
|
|||
|
|
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500"
|
|||
|
|
/>
|
|||
|
|
<button
|
|||
|
|
onClick={() => handleAddComment(selectedEvent.id)}
|
|||
|
|
disabled={!newComment.trim()}
|
|||
|
|
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white rounded-lg transition-colors"
|
|||
|
|
>
|
|||
|
|
Gönder
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</motion.div>
|
|||
|
|
</div>
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
</AnimatePresence>
|
|||
|
|
|
|||
|
|
{/* Photo Viewer Modal */}
|
|||
|
|
<AnimatePresence>
|
|||
|
|
{showPhotoModal && selectedEvent && (
|
|||
|
|
<>
|
|||
|
|
<motion.div
|
|||
|
|
initial={{ opacity: 0 }}
|
|||
|
|
animate={{ opacity: 1 }}
|
|||
|
|
exit={{ opacity: 0 }}
|
|||
|
|
className="fixed inset-0 bg-black/90 z-50"
|
|||
|
|
onClick={() => setShowPhotoModal(false)}
|
|||
|
|
/>
|
|||
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
|||
|
|
<motion.div
|
|||
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|||
|
|
animate={{ opacity: 1, scale: 1 }}
|
|||
|
|
exit={{ opacity: 0, scale: 0.9 }}
|
|||
|
|
className="relative max-w-5xl w-full"
|
|||
|
|
onClick={(e) => e.stopPropagation()}
|
|||
|
|
>
|
|||
|
|
{/* Close Button */}
|
|||
|
|
<button
|
|||
|
|
onClick={() => setShowPhotoModal(false)}
|
|||
|
|
className="absolute top-4 right-4 p-2 bg-black/50 hover:bg-black/70 rounded-full text-white z-10"
|
|||
|
|
>
|
|||
|
|
<HiXMark className="w-6 h-6" />
|
|||
|
|
</button>
|
|||
|
|
|
|||
|
|
{/* Navigation */}
|
|||
|
|
{selectedEvent.photos.length > 1 && (
|
|||
|
|
<>
|
|||
|
|
<button
|
|||
|
|
onClick={() => setSelectedPhotoIndex((prev) =>
|
|||
|
|
prev === 0 ? selectedEvent.photos.length - 1 : prev - 1
|
|||
|
|
)}
|
|||
|
|
className="absolute left-4 top-1/2 -translate-y-1/2 p-2 bg-black/50 hover:bg-black/70 rounded-full text-white"
|
|||
|
|
>
|
|||
|
|
<HiChevronLeft className="w-6 h-6" />
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
onClick={() => setSelectedPhotoIndex((prev) =>
|
|||
|
|
prev === selectedEvent.photos.length - 1 ? 0 : prev + 1
|
|||
|
|
)}
|
|||
|
|
className="absolute right-4 top-1/2 -translate-y-1/2 p-2 bg-black/50 hover:bg-black/70 rounded-full text-white"
|
|||
|
|
>
|
|||
|
|
<HiChevronRight className="w-6 h-6" />
|
|||
|
|
</button>
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Image */}
|
|||
|
|
<img
|
|||
|
|
src={selectedEvent.photos[selectedPhotoIndex]}
|
|||
|
|
alt={`${selectedEvent.title} - ${selectedPhotoIndex + 1}`}
|
|||
|
|
className="w-full h-auto max-h-[80vh] object-contain rounded-lg"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{/* Counter */}
|
|||
|
|
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 px-4 py-2 bg-black/70 text-white rounded-full text-sm">
|
|||
|
|
{selectedPhotoIndex + 1} / {selectedEvent.photos.length}
|
|||
|
|
</div>
|
|||
|
|
</motion.div>
|
|||
|
|
</div>
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
</AnimatePresence>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default EventsModule
|