189 lines
5.9 KiB
JavaScript
189 lines
5.9 KiB
JavaScript
import { useState, useEffect } from 'react'
|
||
import { getEvents, deleteEvent, getEventStats } from '../api/api'
|
||
import './EventList.css'
|
||
|
||
const he = {
|
||
myEvents: 'האירועים שלי',
|
||
newEvent: '+ אירוע חדש',
|
||
noEvents: 'אין לך אירועים עדיין.',
|
||
createFirstEvent: 'צור את האירוע הראשון',
|
||
manage: 'ניהול',
|
||
deleteEvent: 'מחוק אירוע',
|
||
sure: 'האם אתה בטוח שברצונך למחוק אירוע זה? פעולה זו לא ניתן לבטל.',
|
||
guests: 'אורחים',
|
||
confirmed: 'אישרו',
|
||
rate: 'אחוז אישור',
|
||
loadingEvents: 'טוען אירועים...',
|
||
failedLoadEvents: 'נכשל בטעינת אירועים',
|
||
failedDeleteEvent: 'נכשל במחיקת אירוע'
|
||
}
|
||
|
||
function EventList({ onEventSelect, onCreateEvent, onManageTemplates }) {
|
||
const [events, setEvents] = useState([])
|
||
const [loading, setLoading] = useState(true)
|
||
const [error, setError] = useState('')
|
||
const [stats, setStats] = useState({})
|
||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||
|
||
useEffect(() => {
|
||
loadEvents()
|
||
// Set up page visibility listener to refresh when returning to this page
|
||
const handleVisibilityChange = () => {
|
||
if (!document.hidden) {
|
||
loadEvents()
|
||
}
|
||
}
|
||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||
return () => document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||
}, [refreshTrigger])
|
||
|
||
const loadEvents = async () => {
|
||
try {
|
||
setLoading(true)
|
||
const data = await getEvents()
|
||
setEvents(data)
|
||
|
||
// Load stats for each event
|
||
const statsData = {}
|
||
for (const event of data) {
|
||
try {
|
||
statsData[event.id] = await getEventStats(event.id)
|
||
} catch (err) {
|
||
console.error(`Failed to load stats for event ${event.id}:`, err)
|
||
}
|
||
}
|
||
setStats(statsData)
|
||
setError('')
|
||
} catch (err) {
|
||
setError(he.failedLoadEvents)
|
||
console.error(err)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const handleDelete = async (eventId, e) => {
|
||
e.stopPropagation()
|
||
|
||
if (!window.confirm(he.sure)) {
|
||
return
|
||
}
|
||
|
||
try {
|
||
await deleteEvent(eventId)
|
||
setEvents(events.filter(e => e.id !== eventId))
|
||
} catch (err) {
|
||
setError(he.failedDeleteEvent)
|
||
console.error(err)
|
||
}
|
||
}
|
||
|
||
const formatDate = (dateString) => {
|
||
if (!dateString) return 'לא קבוע תאריך'
|
||
const date = new Date(dateString)
|
||
return date.toLocaleDateString('he-IL', {
|
||
year: 'numeric',
|
||
month: 'short',
|
||
day: 'numeric',
|
||
hour: '2-digit',
|
||
minute: '2-digit'
|
||
})
|
||
}
|
||
|
||
if (loading) {
|
||
return <div className="event-list-loading">{he.loadingEvents}</div>
|
||
}
|
||
|
||
return (
|
||
<div className="event-list-container">
|
||
<div className="event-list-header">
|
||
<h1>{he.myEvents}</h1>
|
||
<div className="event-list-header-actions">
|
||
{onManageTemplates && (
|
||
<button onClick={onManageTemplates} className="btn-templates">
|
||
📋 תבניות WhatsApp
|
||
</button>
|
||
)}
|
||
<button onClick={onCreateEvent} className="btn-create-event">
|
||
{he.newEvent}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{error && <div className="error-message">{error}</div>}
|
||
|
||
{events.length === 0 ? (
|
||
<div className="empty-state">
|
||
<p>{he.noEvents}</p>
|
||
<button onClick={onCreateEvent} className="btn-create-event-large">
|
||
{he.createFirstEvent}
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<div className="events-grid">
|
||
{events.map(event => {
|
||
const eventStats = stats[event.id] || { stats: { total: 0, confirmed: 0 } }
|
||
const guestStats = eventStats.stats || { total: 0, confirmed: 0 }
|
||
|
||
return (
|
||
<div
|
||
key={event.id}
|
||
className="event-card"
|
||
onClick={() => onEventSelect(event.id)}
|
||
>
|
||
<div className="event-card-content">
|
||
<h3>{event.name}</h3>
|
||
{event.location && (
|
||
<p className="event-location">📍 {event.location}</p>
|
||
)}
|
||
<p className="event-date">📅 {formatDate(event.date)}</p>
|
||
|
||
<div className="event-stats">
|
||
<div className="stat">
|
||
<span className="stat-label">{he.guests}</span>
|
||
<span className="stat-value">{guestStats.total}</span>
|
||
</div>
|
||
<div className="stat">
|
||
<span className="stat-label">{he.confirmed}</span>
|
||
<span className="stat-value">{guestStats.confirmed}</span>
|
||
</div>
|
||
{guestStats.total > 0 && (
|
||
<div className="stat">
|
||
<span className="stat-label">{he.rate}</span>
|
||
<span className="stat-value">
|
||
{Math.round((guestStats.confirmed / guestStats.total) * 100)}%
|
||
</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="event-card-actions">
|
||
<button
|
||
className="btn-manage"
|
||
onClick={(e) => {
|
||
e.stopPropagation()
|
||
onEventSelect(event.id)
|
||
}}
|
||
>
|
||
{he.manage}
|
||
</button>
|
||
<button
|
||
className="btn-delete"
|
||
onClick={(e) => handleDelete(event.id, e)}
|
||
title={he.deleteEvent}
|
||
>
|
||
🗑️
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)
|
||
})}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default EventList
|