Event editing
This commit is contained in:
@@ -624,4 +624,13 @@ body {
|
|||||||
.event-card {
|
.event-card {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Event modal responsive */
|
||||||
|
.modal-content[style*="600px"] {
|
||||||
|
max-width: 95% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content div[style*="grid-template-columns"] {
|
||||||
|
grid-template-columns: 1fr !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,16 @@ const Dashboard: React.FC = () => {
|
|||||||
const [eventRSVPs, setEventRSVPs] = useState<EventRSVP[]>([]);
|
const [eventRSVPs, setEventRSVPs] = useState<EventRSVP[]>([]);
|
||||||
const [eventRSVPCounts, setEventRSVPCounts] = useState<{[eventId: number]: {attending: number, maybe: number, not_attending: number}}>({});
|
const [eventRSVPCounts, setEventRSVPCounts] = useState<{[eventId: number]: {attending: number, maybe: number, not_attending: number}}>({});
|
||||||
const [rsvpLoading, setRsvpLoading] = useState<{[eventId: number]: boolean}>({});
|
const [rsvpLoading, setRsvpLoading] = useState<{[eventId: number]: boolean}>({});
|
||||||
|
const [showEventModal, setShowEventModal] = useState(false);
|
||||||
|
const [editingEvent, setEditingEvent] = useState<Event | null>(null);
|
||||||
|
const [eventFormData, setEventFormData] = useState({
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
event_date: '',
|
||||||
|
event_time: '',
|
||||||
|
location: '',
|
||||||
|
max_attendees: ''
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!authService.isAuthenticated()) {
|
if (!authService.isAuthenticated()) {
|
||||||
@@ -324,6 +334,82 @@ const Dashboard: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCreateEvent = () => {
|
||||||
|
setEditingEvent(null);
|
||||||
|
setEventFormData({
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
event_date: '',
|
||||||
|
event_time: '',
|
||||||
|
location: '',
|
||||||
|
max_attendees: ''
|
||||||
|
});
|
||||||
|
setShowEventModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditEvent = (event: Event) => {
|
||||||
|
setEditingEvent(event);
|
||||||
|
|
||||||
|
// Convert event_date to YYYY-MM-DD format for date input
|
||||||
|
const dateObj = new Date(event.event_date);
|
||||||
|
const formattedDate = dateObj.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
setEventFormData({
|
||||||
|
title: event.title,
|
||||||
|
description: event.description || '',
|
||||||
|
event_date: formattedDate,
|
||||||
|
event_time: event.event_time || '',
|
||||||
|
location: event.location || '',
|
||||||
|
max_attendees: event.max_attendees?.toString() || ''
|
||||||
|
});
|
||||||
|
setShowEventModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEventFormChange = (field: string, value: string) => {
|
||||||
|
setEventFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
[field]: value
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveEvent = async () => {
|
||||||
|
try {
|
||||||
|
const eventData = {
|
||||||
|
title: eventFormData.title,
|
||||||
|
description: eventFormData.description || undefined,
|
||||||
|
event_date: eventFormData.event_date,
|
||||||
|
event_time: eventFormData.event_time || undefined,
|
||||||
|
location: eventFormData.location || undefined,
|
||||||
|
max_attendees: eventFormData.max_attendees ? parseInt(eventFormData.max_attendees) : undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
if (editingEvent) {
|
||||||
|
// Update existing event
|
||||||
|
await eventService.updateEvent(editingEvent.id, eventData);
|
||||||
|
} else {
|
||||||
|
// Create new event
|
||||||
|
await eventService.createEvent(eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload events
|
||||||
|
const eventsData = await eventService.getAllEvents();
|
||||||
|
setAllEvents(eventsData);
|
||||||
|
await loadEventRSVPCounts(eventsData);
|
||||||
|
|
||||||
|
// Close modal
|
||||||
|
setShowEventModal(false);
|
||||||
|
setEditingEvent(null);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save event:', error);
|
||||||
|
alert('Failed to save event. Please try again.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseEventModal = () => {
|
||||||
|
setShowEventModal(false);
|
||||||
|
setEditingEvent(null);
|
||||||
|
};
|
||||||
|
|
||||||
const formatDate = (dateString: string) => {
|
const formatDate = (dateString: string) => {
|
||||||
return new Date(dateString).toLocaleDateString('en-GB', {
|
return new Date(dateString).toLocaleDateString('en-GB', {
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
@@ -710,7 +796,7 @@ const Dashboard: React.FC = () => {
|
|||||||
<div style={{ marginBottom: '16px' }}>
|
<div style={{ marginBottom: '16px' }}>
|
||||||
<button
|
<button
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
onClick={() => {/* TODO: Implement create event modal */}}
|
onClick={handleCreateEvent}
|
||||||
style={{ fontSize: '14px', padding: '8px 16px' }}
|
style={{ fontSize: '14px', padding: '8px 16px' }}
|
||||||
>
|
>
|
||||||
Create New Event
|
Create New Event
|
||||||
@@ -768,7 +854,7 @@ const Dashboard: React.FC = () => {
|
|||||||
<div style={{ display: 'flex', gap: '4px' }}>
|
<div style={{ display: 'flex', gap: '4px' }}>
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={() => {/* TODO: Implement edit event */}}
|
onClick={() => handleEditEvent(event)}
|
||||||
style={{ fontSize: '12px', padding: '4px 8px' }}
|
style={{ fontSize: '12px', padding: '4px 8px' }}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
@@ -1049,6 +1135,104 @@ const Dashboard: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Event Create/Edit Modal */}
|
||||||
|
{showEventModal && (
|
||||||
|
<div className="modal-overlay">
|
||||||
|
<div className="modal-content" style={{ maxWidth: '600px' }}>
|
||||||
|
<h3>{editingEvent ? 'Edit Event' : 'Create New Event'}</h3>
|
||||||
|
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Event Title *</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={eventFormData.title}
|
||||||
|
onChange={(e) => handleEventFormChange('title', e.target.value)}
|
||||||
|
required
|
||||||
|
placeholder="Annual General Meeting"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Description</label>
|
||||||
|
<textarea
|
||||||
|
value={eventFormData.description}
|
||||||
|
onChange={(e) => handleEventFormChange('description', e.target.value)}
|
||||||
|
rows={4}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '8px',
|
||||||
|
border: '1px solid #ddd',
|
||||||
|
borderRadius: '4px',
|
||||||
|
fontSize: '16px',
|
||||||
|
resize: 'vertical'
|
||||||
|
}}
|
||||||
|
placeholder="Event details and agenda..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Event Date *</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
value={eventFormData.event_date}
|
||||||
|
onChange={(e) => handleEventFormChange('event_date', e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Event Time</label>
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
value={eventFormData.event_time}
|
||||||
|
onChange={(e) => handleEventFormChange('event_time', e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Location</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={eventFormData.location}
|
||||||
|
onChange={(e) => handleEventFormChange('location', e.target.value)}
|
||||||
|
placeholder="Swansea Airport Conference Room"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-form-group">
|
||||||
|
<label>Max Attendees (optional)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={eventFormData.max_attendees}
|
||||||
|
onChange={(e) => handleEventFormChange('max_attendees', e.target.value)}
|
||||||
|
min="1"
|
||||||
|
placeholder="Leave blank for unlimited"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-buttons">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleCloseEventModal}
|
||||||
|
className="modal-btn-cancel"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSaveEvent}
|
||||||
|
className="modal-btn-primary"
|
||||||
|
disabled={!eventFormData.title || !eventFormData.event_date}
|
||||||
|
>
|
||||||
|
{editingEvent ? 'Update Event' : 'Create Event'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user