Implement event completion workflow (Task 14)
- Add completeEvent endpoint to backend API - Create EventCompletionForm component with litter quantity input and photo upload - Update EventDetailModal to show completion form for organizers - Add isOrganizer check in EventsPage - Update event service to support completion - Display completion data (litter collected, photos) for completed events
This commit is contained in:
@@ -343,4 +343,66 @@ export const eventController = {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Complete event
|
||||
async completeEvent(req: AuthRequest, res: Response) {
|
||||
try {
|
||||
const clerkId = req.userId;
|
||||
if (!clerkId) {
|
||||
return res.status(401).json({
|
||||
code: 'UNAUTHORIZED',
|
||||
message: 'User not authenticated',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
const userId = await findOrCreateUser(clerkId);
|
||||
|
||||
const { id } = req.params;
|
||||
const event = await eventService.getEventById(id);
|
||||
|
||||
if (!event) {
|
||||
return res.status(404).json({
|
||||
code: 'EVENT_NOT_FOUND',
|
||||
message: 'Event not found',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is the organizer
|
||||
if (event.organizerId !== userId) {
|
||||
return res.status(403).json({
|
||||
code: 'FORBIDDEN',
|
||||
message: 'Only the event organizer can complete this event',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
const { litterCollected, photos } = req.body;
|
||||
|
||||
// Validation
|
||||
if (litterCollected === undefined || litterCollected === null) {
|
||||
return res.status(400).json({
|
||||
code: 'VALIDATION_ERROR',
|
||||
message: 'litterCollected is required',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
const completedEvent = await eventService.completeEvent(id, {
|
||||
litterCollected: parseFloat(litterCollected),
|
||||
photos: photos || [],
|
||||
});
|
||||
|
||||
res.json(completedEvent);
|
||||
} catch (error: any) {
|
||||
console.error('Error completing event:', error);
|
||||
res.status(500).json({
|
||||
code: 'COMPLETE_EVENT_ERROR',
|
||||
message: 'Failed to complete event',
|
||||
details: error.message,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,5 +16,6 @@ router.delete('/:id', requireAuth, eventController.deleteEvent);
|
||||
router.post('/:id/register', requireAuth, eventController.registerForEvent);
|
||||
router.delete('/:id/register', requireAuth, eventController.unregisterFromEvent);
|
||||
router.get('/:id/registration-status', requireAuth, eventController.getRegistrationStatus);
|
||||
router.post('/:id/complete', requireAuth, eventController.completeEvent);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -324,4 +324,40 @@ export const eventService = {
|
||||
|
||||
return !!registration;
|
||||
},
|
||||
|
||||
async completeEvent(eventId: string, data: { litterCollected: number; photos?: string[] }) {
|
||||
const event = await prisma.event.update({
|
||||
where: { id: eventId },
|
||||
data: {
|
||||
status: 'completed',
|
||||
litterCollected: data.litterCollected,
|
||||
photos: data.photos || [],
|
||||
},
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
registrations: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
organizerId: event.organizerId,
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
latitude: parseFloat(event.latitude.toString()),
|
||||
longitude: parseFloat(event.longitude.toString()),
|
||||
locationName: event.locationName,
|
||||
scheduledDate: event.scheduledDate,
|
||||
duration: event.duration,
|
||||
status: event.status || 'upcoming',
|
||||
participantCount: event._count.registrations,
|
||||
litterCollected: event.litterCollected ? parseFloat(event.litterCollected.toString()) : undefined,
|
||||
photos: event.photos ? (Array.isArray(event.photos) ? event.photos : []) : undefined,
|
||||
createdAt: event.createdAt,
|
||||
updatedAt: event.updatedAt,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user