Add equipment management to events
- Add equipmentProvided and requiredItems fields to Event model - Update event creation form with equipment section - Allow organizers to specify if equipment is provided or BYO - Display required items list in event details - Update database schema and run migration
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
-- Add equipment fields to events table
|
||||
ALTER TABLE `events` ADD COLUMN `equipment_provided` BOOLEAN DEFAULT false AFTER `photos`;
|
||||
ALTER TABLE `events` ADD COLUMN `required_items` JSON AFTER `equipment_provided`;
|
||||
@@ -83,6 +83,8 @@ model Event {
|
||||
participantCount Int? @default(0) @map("participant_count")
|
||||
litterCollected Decimal? @map("litter_collected") @db.Decimal(10, 2)
|
||||
photos Json?
|
||||
equipmentProvided Boolean? @default(false) @map("equipment_provided")
|
||||
requiredItems Json? @map("required_items")
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0)
|
||||
updatedAt DateTime? @default(now()) @updatedAt @map("updated_at") @db.Timestamp(0)
|
||||
registrations EventRegistration[]
|
||||
|
||||
@@ -109,7 +109,7 @@ export const eventController = {
|
||||
// Find or create user in database
|
||||
const userId = await findOrCreateUser(clerkId);
|
||||
|
||||
const { title, description, latitude, longitude, locationName, scheduledDate, duration } = req.body;
|
||||
const { title, description, latitude, longitude, locationName, scheduledDate, duration, equipmentProvided, requiredItems } = req.body;
|
||||
|
||||
// Validation
|
||||
if (!title || !description || !latitude || !longitude || !locationName || !scheduledDate || !duration) {
|
||||
@@ -129,6 +129,8 @@ export const eventController = {
|
||||
locationName,
|
||||
scheduledDate: new Date(scheduledDate),
|
||||
duration: parseInt(duration),
|
||||
equipmentProvided: equipmentProvided !== undefined ? Boolean(equipmentProvided) : false,
|
||||
requiredItems: Array.isArray(requiredItems) ? requiredItems : [],
|
||||
};
|
||||
|
||||
const event = await eventService.createEvent(eventData);
|
||||
|
||||
@@ -21,6 +21,8 @@ interface CreateEventData {
|
||||
locationName: string;
|
||||
scheduledDate: Date;
|
||||
duration: number;
|
||||
equipmentProvided?: boolean;
|
||||
requiredItems?: string[];
|
||||
}
|
||||
|
||||
interface UpdateEventData {
|
||||
@@ -31,6 +33,8 @@ interface UpdateEventData {
|
||||
status?: 'upcoming' | 'completed' | 'cancelled';
|
||||
litterCollected?: number;
|
||||
photos?: string[];
|
||||
equipmentProvided?: boolean;
|
||||
requiredItems?: string[];
|
||||
}
|
||||
|
||||
export const eventService = {
|
||||
@@ -93,6 +97,8 @@ export const eventService = {
|
||||
participantCount: event._count.registrations,
|
||||
litterCollected: event.litterCollected ? parseFloat(event.litterCollected.toString()) : undefined,
|
||||
photos: event.photos ? (Array.isArray(event.photos) ? event.photos : []) : undefined,
|
||||
equipmentProvided: (event as any).equipmentProvided || false,
|
||||
requiredItems: (event as any).requiredItems ? (Array.isArray((event as any).requiredItems) ? (event as any).requiredItems : []) : [],
|
||||
createdAt: event.createdAt,
|
||||
updatedAt: event.updatedAt,
|
||||
}));
|
||||
@@ -137,6 +143,8 @@ export const eventService = {
|
||||
participantCount: event._count.registrations,
|
||||
litterCollected: event.litterCollected ? parseFloat(event.litterCollected.toString()) : undefined,
|
||||
photos: event.photos ? (Array.isArray(event.photos) ? event.photos : []) : undefined,
|
||||
equipmentProvided: (event as any).equipmentProvided || false,
|
||||
requiredItems: (event as any).requiredItems ? (Array.isArray((event as any).requiredItems) ? (event as any).requiredItems : []) : [],
|
||||
createdAt: event.createdAt,
|
||||
updatedAt: event.updatedAt,
|
||||
};
|
||||
@@ -145,16 +153,18 @@ export const eventService = {
|
||||
async createEvent(data: CreateEventData) {
|
||||
// Create point geometry for spatial queries
|
||||
const locationPoint = `POINT(${data.longitude} ${data.latitude})`;
|
||||
const equipmentProvided = data.equipmentProvided !== undefined ? data.equipmentProvided : false;
|
||||
const requiredItems = data.requiredItems && data.requiredItems.length > 0 ? JSON.stringify(data.requiredItems) : null;
|
||||
|
||||
const event = await prisma.$executeRaw`
|
||||
INSERT INTO events (
|
||||
id, organizer_id, title, description, location, latitude, longitude,
|
||||
location_name, scheduled_date, duration, status, participant_count
|
||||
location_name, scheduled_date, duration, status, participant_count, equipment_provided, required_items
|
||||
) VALUES (
|
||||
UUID(), ${data.organizerId}, ${data.title}, ${data.description},
|
||||
ST_GeomFromText(${locationPoint}, 4326),
|
||||
${data.latitude}, ${data.longitude}, ${data.locationName},
|
||||
${data.scheduledDate}, ${data.duration}, 'upcoming', 0
|
||||
${data.scheduledDate}, ${data.duration}, 'upcoming', 0, ${equipmentProvided}, ${requiredItems}
|
||||
)
|
||||
`;
|
||||
|
||||
@@ -195,6 +205,8 @@ export const eventService = {
|
||||
participantCount: createdEvent._count.registrations,
|
||||
litterCollected: createdEvent.litterCollected ? parseFloat(createdEvent.litterCollected.toString()) : undefined,
|
||||
photos: createdEvent.photos ? (Array.isArray(createdEvent.photos) ? createdEvent.photos : []) : undefined,
|
||||
equipmentProvided: (createdEvent as any).equipmentProvided || false,
|
||||
requiredItems: (createdEvent as any).requiredItems ? (Array.isArray((createdEvent as any).requiredItems) ? (createdEvent as any).requiredItems : []) : [],
|
||||
createdAt: createdEvent.createdAt,
|
||||
updatedAt: createdEvent.updatedAt,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user