diff --git a/backend/prisma/seed.ts b/backend/prisma/seed.ts index d3b41b6..8960839 100644 --- a/backend/prisma/seed.ts +++ b/backend/prisma/seed.ts @@ -3,145 +3,153 @@ import { PrismaClient, Role, Department, ArrivalMode, EventType, EventStatus, Ve const prisma = new PrismaClient(); async function main() { - console.log('🌱 Seeding database...'); + console.log('🌱 Seeding database with BSA Jamboree scenario...'); - // Clean up existing data (careful in production!) + // Clean up existing data (preserves users/auth accounts) await prisma.scheduleEvent.deleteMany({}); await prisma.flight.deleteMany({}); await prisma.vehicle.deleteMany({}); - await prisma.driver.deleteMany({}); + // Don't delete drivers linked to users — only standalone test drivers + await prisma.driver.deleteMany({ where: { userId: null } }); await prisma.vIP.deleteMany({}); - await prisma.user.deleteMany({}); - console.log('āœ… Cleared existing data'); + console.log('āœ… Cleared existing test data (preserved user accounts)'); - // Create sample users - const admin = await prisma.user.create({ + // ============================================= + // VEHICLES — BSA Jamboree fleet + // ============================================= + + const suburban1 = await prisma.vehicle.create({ data: { - auth0Id: 'auth0|admin-sample-id', - email: 'admin@example.com', - name: 'Admin User', - role: Role.ADMINISTRATOR, - isApproved: true, - }, - }); - - const coordinator = await prisma.user.create({ - data: { - auth0Id: 'auth0|coordinator-sample-id', - email: 'coordinator@example.com', - name: 'Coordinator User', - role: Role.COORDINATOR, - isApproved: true, - }, - }); - - // Note: test@test.com user is auto-created and auto-approved on first login (see auth.service.ts) - - console.log('āœ… Created sample users'); - - // Create sample vehicles with capacity - const blackSUV = await prisma.vehicle.create({ - data: { - name: 'Black Suburban', + name: 'Black Suburban #1', type: VehicleType.SUV, - licensePlate: 'ABC-1234', + licensePlate: 'BSA-001', seatCapacity: 6, status: VehicleStatus.AVAILABLE, - notes: 'Leather interior, tinted windows', + notes: 'Primary VIP vehicle, leather interior', + }, + }); + + const suburban2 = await prisma.vehicle.create({ + data: { + name: 'Black Suburban #2', + type: VehicleType.SUV, + licensePlate: 'BSA-002', + seatCapacity: 6, + status: VehicleStatus.AVAILABLE, + notes: 'Secondary VIP vehicle', }, }); const whiteVan = await prisma.vehicle.create({ data: { - name: 'White Sprinter Van', + name: 'White 15-Passenger Van', type: VehicleType.VAN, - licensePlate: 'XYZ-5678', - seatCapacity: 12, + licensePlate: 'BSA-003', + seatCapacity: 14, status: VehicleStatus.AVAILABLE, - notes: 'High roof, wheelchair accessible', + notes: 'Large group transport', }, }); - const blueSedan = await prisma.vehicle.create({ + const golfCart1 = await prisma.vehicle.create({ data: { - name: 'Blue Camry', - type: VehicleType.SEDAN, - licensePlate: 'DEF-9012', + name: 'Golf Cart A', + type: VehicleType.GOLF_CART, + licensePlate: 'GC-A', seatCapacity: 4, status: VehicleStatus.AVAILABLE, - notes: 'Fuel efficient, good for short trips', + notes: 'On-site shuttle between venues', }, }); - const grayBus = await prisma.vehicle.create({ + const golfCart2 = await prisma.vehicle.create({ data: { - name: 'Gray Charter Bus', - type: VehicleType.BUS, - licensePlate: 'BUS-0001', - seatCapacity: 40, + name: 'Golf Cart B', + type: VehicleType.GOLF_CART, + licensePlate: 'GC-B', + seatCapacity: 4, status: VehicleStatus.AVAILABLE, - notes: 'Full size charter bus, A/C, luggage compartment', + notes: 'On-site shuttle between venues', }, }); - console.log('āœ… Created sample vehicles with capacities'); - - // Create sample drivers - const driver1 = await prisma.driver.create({ + const charterBus = await prisma.vehicle.create({ data: { - name: 'John Smith', - phone: '+1 (555) 123-4567', - department: Department.OFFICE_OF_DEVELOPMENT, + name: 'Charter Bus', + type: VehicleType.BUS, + licensePlate: 'BSA-BUS', + seatCapacity: 45, + status: VehicleStatus.AVAILABLE, + notes: 'Full-size charter for large group moves', }, }); - const driver2 = await prisma.driver.create({ + console.log('āœ… Created 6 vehicles'); + + // ============================================= + // DRIVERS + // ============================================= + + const driverTom = await prisma.driver.create({ data: { - name: 'Jane Doe', - phone: '+1 (555) 987-6543', + name: 'Tom Bradley', + phone: '+1 (555) 100-0001', department: Department.ADMIN, }, }); - const driver3 = await prisma.driver.create({ + const driverMaria = await prisma.driver.create({ data: { - name: 'Amanda Washington', - phone: '+1 (555) 234-5678', - department: Department.OFFICE_OF_DEVELOPMENT, - }, - }); - - const driver4 = await prisma.driver.create({ - data: { - name: 'Michael Thompson', - phone: '+1 (555) 876-5432', + name: 'Maria Gonzalez', + phone: '+1 (555) 100-0002', department: Department.ADMIN, }, }); - console.log('āœ… Created sample drivers'); - - // Create sample VIPs - const vip1 = await prisma.vIP.create({ + const driverKevin = await prisma.driver.create({ data: { - name: 'Dr. Robert Johnson', - organization: 'Tech Corporation', + name: 'Kevin Park', + phone: '+1 (555) 100-0003', + department: Department.OFFICE_OF_DEVELOPMENT, + }, + }); + + const driverLisa = await prisma.driver.create({ + data: { + name: 'Lisa Chen', + phone: '+1 (555) 100-0004', + department: Department.OFFICE_OF_DEVELOPMENT, + }, + }); + + console.log('āœ… Created 4 drivers'); + + // ============================================= + // VIPs — BSA Jamboree dignitaries WITH PARTY SIZES + // ============================================= + + // Chief Scout Executive — travels with 2 handlers + const vipRoger = await prisma.vIP.create({ + data: { + name: 'Roger Mosby', + organization: 'Boy Scouts of America', department: Department.OFFICE_OF_DEVELOPMENT, arrivalMode: ArrivalMode.FLIGHT, airportPickup: true, venueTransport: true, - notes: 'Prefers window seat, dietary restriction: vegetarian', + partySize: 3, // Roger + 2 handlers + notes: 'Chief Scout Executive. Travels with 2 staff handlers. Requires accessible vehicle.', flights: { create: [ { - flightNumber: 'AA123', - flightDate: new Date('2026-02-15'), + flightNumber: 'UA1142', + flightDate: new Date('2026-02-05'), segment: 1, - departureAirport: 'JFK', - arrivalAirport: 'LAX', - scheduledDeparture: new Date('2026-02-15T08:00:00'), - scheduledArrival: new Date('2026-02-15T11:30:00'), + departureAirport: 'IAD', + arrivalAirport: 'DEN', + scheduledDeparture: new Date('2026-02-05T07:00:00'), + scheduledArrival: new Date('2026-02-05T09:15:00'), status: 'scheduled', }, ], @@ -149,199 +157,516 @@ async function main() { }, }); - const vip2 = await prisma.vIP.create({ + // National Board Chair — travels with spouse + const vipPatricia = await prisma.vIP.create({ data: { - name: 'Ms. Sarah Williams', - organization: 'Global Foundation', + name: 'Patricia Hawkins', + organization: 'BSA National Board', + department: Department.OFFICE_OF_DEVELOPMENT, + arrivalMode: ArrivalMode.FLIGHT, + airportPickup: true, + venueTransport: true, + partySize: 2, // Patricia + spouse + notes: 'National Board Chair. Traveling with husband (Richard). Both attend all events.', + flights: { + create: [ + { + flightNumber: 'DL783', + flightDate: new Date('2026-02-05'), + segment: 1, + departureAirport: 'ATL', + arrivalAirport: 'DEN', + scheduledDeparture: new Date('2026-02-05T06:30:00'), + scheduledArrival: new Date('2026-02-05T08:45:00'), + status: 'scheduled', + }, + ], + }, + }, + }); + + // Major Donor — solo + const vipJames = await prisma.vIP.create({ + data: { + name: 'James Whitfield III', + organization: 'Whitfield Foundation', + department: Department.OFFICE_OF_DEVELOPMENT, + arrivalMode: ArrivalMode.FLIGHT, + airportPickup: true, + venueTransport: true, + partySize: 1, // Solo + notes: 'Major donor ($2M+). Eagle Scout class of 1978. Very punctual — do not be late.', + flights: { + create: [ + { + flightNumber: 'AA456', + flightDate: new Date('2026-02-05'), + segment: 1, + departureAirport: 'DFW', + arrivalAirport: 'DEN', + scheduledDeparture: new Date('2026-02-05T10:00:00'), + scheduledArrival: new Date('2026-02-05T11:30:00'), + status: 'scheduled', + }, + ], + }, + }, + }); + + // Keynote Speaker — travels with assistant + const vipDrBaker = await prisma.vIP.create({ + data: { + name: 'Dr. Angela Baker', + organization: 'National Geographic Society', + department: Department.OFFICE_OF_DEVELOPMENT, + arrivalMode: ArrivalMode.FLIGHT, + airportPickup: true, + venueTransport: true, + partySize: 2, // Dr. Baker + assistant + notes: 'Keynote speaker, Day 1. Traveling with assistant (Marcus). Needs quiet space before keynote.', + flights: { + create: [ + { + flightNumber: 'SW221', + flightDate: new Date('2026-02-05'), + segment: 1, + departureAirport: 'BWI', + arrivalAirport: 'DEN', + scheduledDeparture: new Date('2026-02-05T08:15:00'), + scheduledArrival: new Date('2026-02-05T10:40:00'), + status: 'scheduled', + }, + ], + }, + }, + }); + + // Governor — travels with 3 (security detail + aide) + const vipGovMartinez = await prisma.vIP.create({ + data: { + name: 'Gov. Carlos Martinez', + organization: 'State of Colorado', department: Department.ADMIN, arrivalMode: ArrivalMode.SELF_DRIVING, - expectedArrival: new Date('2026-02-16T14:00:00'), + expectedArrival: new Date('2026-02-05T13:00:00'), airportPickup: false, venueTransport: true, - notes: 'Bringing assistant', + partySize: 4, // Governor + security officer + aide + driver (their own driver stays) + notes: 'Governor arriving by motorcade. Party of 4: Gov, 1 state trooper, 1 aide, 1 advance staff. Their driver does NOT need a seat.', }, }); - const vip3 = await prisma.vIP.create({ + // Local Council President — solo, self-driving + const vipSusan = await prisma.vIP.create({ data: { - name: 'Emily Richardson (Harvard University)', - organization: 'Harvard University', - department: Department.OFFICE_OF_DEVELOPMENT, - arrivalMode: ArrivalMode.FLIGHT, - airportPickup: true, + name: 'Susan O\'Malley', + organization: 'Denver Area Council BSA', + department: Department.ADMIN, + arrivalMode: ArrivalMode.SELF_DRIVING, + expectedArrival: new Date('2026-02-05T08:00:00'), + airportPickup: false, venueTransport: true, - notes: 'Board member, requires accessible vehicle', + partySize: 1, + notes: 'Local council president. Knows the venue well. Can help with directions if needed.', }, }); - const vip4 = await prisma.vIP.create({ + console.log('āœ… Created 6 VIPs with party sizes'); + console.log(' Roger Mosby (party: 3), Patricia Hawkins (party: 2)'); + console.log(' James Whitfield III (party: 1), Dr. Angela Baker (party: 2)'); + console.log(' Gov. Martinez (party: 4), Susan O\'Malley (party: 1)'); + + // ============================================= + // SHARED ITINERARY ITEMS (master events) + // These are the actual activities everyone attends + // ============================================= + + // Use dates relative to "today + 2 days" so they show up in the War Room + const jamboreeDay1 = new Date(); + jamboreeDay1.setDate(jamboreeDay1.getDate() + 2); + jamboreeDay1.setHours(0, 0, 0, 0); + + const jamboreeDay2 = new Date(jamboreeDay1); + jamboreeDay2.setDate(jamboreeDay2.getDate() + 1); + + // Day 1 shared events + const openingCeremony = await prisma.scheduleEvent.create({ data: { - name: 'David Chen (Stanford)', - organization: 'Stanford University', - department: Department.OFFICE_OF_DEVELOPMENT, - arrivalMode: ArrivalMode.FLIGHT, - airportPickup: true, - venueTransport: true, - notes: 'Keynote speaker', - }, - }); - - console.log('āœ… Created sample VIPs'); - - // Create sample schedule events (unified activities) - NOW WITH MULTIPLE VIPS! - - // Multi-VIP rideshare to Campfire Night (3 VIPs in one SUV) - await prisma.scheduleEvent.create({ - data: { - vipIds: [vip3.id, vip4.id, vip1.id], // 3 VIPs sharing a ride - title: 'Transport to Campfire Night', - pickupLocation: 'Grand Hotel Lobby', - dropoffLocation: 'Camp Amphitheater', - startTime: new Date('2026-02-15T19:45:00'), - endTime: new Date('2026-02-15T20:00:00'), - description: 'Rideshare: Emily, David, and Dr. Johnson to campfire', - type: EventType.TRANSPORT, - status: EventStatus.SCHEDULED, - driverId: driver3.id, - vehicleId: blackSUV.id, // 3 VIPs in 6-seat SUV (3/6 seats used) - }, - }); - - // Single VIP transport - await prisma.scheduleEvent.create({ - data: { - vipIds: [vip1.id], - title: 'Airport Pickup - Dr. Johnson', - pickupLocation: 'LAX Terminal 4', - dropoffLocation: 'Grand Hotel', - startTime: new Date('2026-02-15T11:30:00'), - endTime: new Date('2026-02-15T12:30:00'), - description: 'Pick up Dr. Johnson from LAX', - type: EventType.TRANSPORT, - status: EventStatus.SCHEDULED, - driverId: driver1.id, - vehicleId: blueSedan.id, // 1 VIP in 4-seat sedan (1/4 seats used) - }, - }); - - // Two VIPs sharing lunch transport - await prisma.scheduleEvent.create({ - data: { - vipIds: [vip1.id, vip2.id], - title: 'Transport to Lunch - Day 1', - pickupLocation: 'Grand Hotel Lobby', - dropoffLocation: 'Main Dining Hall', - startTime: new Date('2026-02-15T11:45:00'), - endTime: new Date('2026-02-15T12:00:00'), - description: 'Rideshare: Dr. Johnson and Ms. Williams to lunch', - type: EventType.TRANSPORT, - status: EventStatus.SCHEDULED, - driverId: driver2.id, - vehicleId: blueSedan.id, // 2 VIPs in 4-seat sedan (2/4 seats used) - }, - }); - - // Large group transport in van - await prisma.scheduleEvent.create({ - data: { - vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], - title: 'Morning Shuttle to Conference', - pickupLocation: 'Grand Hotel Lobby', - dropoffLocation: 'Conference Center', - startTime: new Date('2026-02-15T08:00:00'), - endTime: new Date('2026-02-15T08:30:00'), - description: 'All VIPs to morning conference session', - type: EventType.TRANSPORT, - status: EventStatus.SCHEDULED, - driverId: driver4.id, - vehicleId: whiteVan.id, // 4 VIPs in 12-seat van (4/12 seats used) - }, - }); - - // Non-transport activities (unified system) - - // Opening Ceremony - all VIPs attending - await prisma.scheduleEvent.create({ - data: { - vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id], title: 'Opening Ceremony', - location: 'Main Stage', - startTime: new Date('2026-02-15T10:00:00'), - endTime: new Date('2026-02-15T11:30:00'), - description: 'Welcome and opening remarks', + location: 'Main Arena', + startTime: new Date(jamboreeDay1.getTime() + 10 * 60 * 60 * 1000), // 10:00 AM + endTime: new Date(jamboreeDay1.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM + description: 'National anthem, color guard, welcome remarks by Chief Scout Executive. All VIPs seated in reserved section.', type: EventType.EVENT, status: EventStatus.SCHEDULED, }, }); - // Lunch - Day 1 (all VIPs) - await prisma.scheduleEvent.create({ + const vipLuncheon = await prisma.scheduleEvent.create({ data: { - vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], - title: 'Lunch - Day 1', - location: 'Main Dining Hall', - startTime: new Date('2026-02-15T12:00:00'), - endTime: new Date('2026-02-15T13:30:00'), - description: 'Day 1 lunch for all attendees', + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id], + title: 'VIP Luncheon', + location: 'Eagle Lodge Private Dining', + startTime: new Date(jamboreeDay1.getTime() + 12 * 60 * 60 * 1000), // 12:00 PM + endTime: new Date(jamboreeDay1.getTime() + 13.5 * 60 * 60 * 1000), // 1:30 PM + description: 'Private luncheon for VIP guests and BSA leadership. Seated service.', type: EventType.MEAL, status: EventStatus.SCHEDULED, }, }); - // Campfire Night (all VIPs) - await prisma.scheduleEvent.create({ + const keynoteAddress = await prisma.scheduleEvent.create({ data: { - vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], - title: 'Campfire Night', - location: 'Camp Amphitheater', - startTime: new Date('2026-02-15T20:00:00'), - endTime: new Date('2026-02-15T22:00:00'), - description: 'Evening campfire and networking', + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Keynote Address — Dr. Baker', + location: 'Main Arena', + startTime: new Date(jamboreeDay1.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM + endTime: new Date(jamboreeDay1.getTime() + 15.5 * 60 * 60 * 1000), // 3:30 PM + description: 'Dr. Angela Baker delivers keynote on "Adventure and Discovery." VIPs in reserved front section.', type: EventType.EVENT, status: EventStatus.SCHEDULED, + notes: 'Gov. Martinez departs before keynote — not attending this one.', }, }); - // Private meeting - just Dr. Johnson and Ms. Williams - await prisma.scheduleEvent.create({ + const donorMeeting = await prisma.scheduleEvent.create({ data: { - vipIds: [vip1.id, vip2.id], - title: 'Donor Meeting', - location: 'Conference Room A', - startTime: new Date('2026-02-15T14:00:00'), - endTime: new Date('2026-02-15T15:00:00'), - description: 'Private meeting with development team', + vipIds: [vipJames.id, vipPatricia.id, vipRoger.id], + title: 'Donor Strategy Meeting', + location: 'Eagle Lodge Conference Room', + startTime: new Date(jamboreeDay1.getTime() + 16 * 60 * 60 * 1000), // 4:00 PM + endTime: new Date(jamboreeDay1.getTime() + 17 * 60 * 60 * 1000), // 5:00 PM + description: 'Private meeting: Whitfield Foundation partnership discussion with BSA leadership.', type: EventType.MEETING, status: EventStatus.SCHEDULED, }, }); - console.log('āœ… Created sample schedule events with multi-VIP rideshares and activities'); + const campfireNight = await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Campfire Night', + location: 'Campfire Bowl', + startTime: new Date(jamboreeDay1.getTime() + 20 * 60 * 60 * 1000), // 8:00 PM + endTime: new Date(jamboreeDay1.getTime() + 22 * 60 * 60 * 1000), // 10:00 PM + description: 'Traditional Jamboree campfire with skits, songs, and awards. VIP seating near stage.', + type: EventType.EVENT, + status: EventStatus.SCHEDULED, + }, + }); - console.log('\nšŸŽ‰ Database seeded successfully!'); - console.log('\nSample Users:'); - console.log('- Admin: admin@example.com'); - console.log('- Coordinator: coordinator@example.com'); - console.log('\nSample VIPs:'); - console.log('- Dr. Robert Johnson (Flight arrival)'); - console.log('- Ms. Sarah Williams (Self-driving)'); - console.log('- Emily Richardson (Harvard University)'); - console.log('- David Chen (Stanford)'); - console.log('\nSample Drivers:'); - console.log('- John Smith'); - console.log('- Jane Doe'); - console.log('- Amanda Washington'); - console.log('- Michael Thompson'); - console.log('\nSample Vehicles:'); - console.log('- Black Suburban (SUV, 6 seats)'); - console.log('- White Sprinter Van (Van, 12 seats)'); - console.log('- Blue Camry (Sedan, 4 seats)'); - console.log('- Gray Charter Bus (Bus, 40 seats)'); - console.log('\nSchedule Tasks (Multi-VIP Examples):'); - console.log('- 3 VIPs sharing SUV to Campfire (3/6 seats)'); - console.log('- 2 VIPs sharing sedan to Lunch (2/4 seats)'); - console.log('- 4 VIPs in van to Conference (4/12 seats)'); - console.log('- 1 VIP solo in sedan from Airport (1/4 seats)'); + // Day 2 shared events + const eagleScoutCeremony = await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipSusan.id], + title: 'Eagle Scout Recognition Ceremony', + location: 'Main Arena', + startTime: new Date(jamboreeDay2.getTime() + 9 * 60 * 60 * 1000), // 9:00 AM + endTime: new Date(jamboreeDay2.getTime() + 11 * 60 * 60 * 1000), // 11:00 AM + description: 'Honoring 200+ new Eagle Scouts. James Whitfield giving remarks as Eagle Scout alumnus.', + type: EventType.EVENT, + status: EventStatus.SCHEDULED, + }, + }); + + const farewellBrunch = await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Farewell Brunch', + location: 'Eagle Lodge Private Dining', + startTime: new Date(jamboreeDay2.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM + endTime: new Date(jamboreeDay2.getTime() + 13 * 60 * 60 * 1000), // 1:00 PM + description: 'Final meal together before departures. Thank-you gifts distributed.', + type: EventType.MEAL, + status: EventStatus.SCHEDULED, + }, + }); + + console.log('āœ… Created 7 shared itinerary items (master events)'); + + // ============================================= + // TRANSPORT LEGS — linked to master events + // These are the rides TO and FROM the shared events + // ============================================= + + // --- AIRPORT PICKUPS (Day 1 morning) --- + + // Roger Mosby (party of 3) — airport pickup + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id], + title: 'Airport Pickup — Roger Mosby', + pickupLocation: 'DEN Terminal West, Door 507', + dropoffLocation: 'Jamboree Camp — VIP Lodge', + startTime: new Date('2026-02-05T09:15:00'), + endTime: new Date('2026-02-05T10:00:00'), + description: 'Party of 3 (Roger + 2 handlers). UA1142 lands 9:15 AM.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: suburban1.id, // 3 people in 6-seat SUV + }, + }); + + // Patricia Hawkins (party of 2) — airport pickup + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipPatricia.id], + title: 'Airport Pickup — Patricia Hawkins', + pickupLocation: 'DEN Terminal South, Door 610', + dropoffLocation: 'Jamboree Camp — VIP Lodge', + startTime: new Date('2026-02-05T08:45:00'), + endTime: new Date('2026-02-05T09:30:00'), + description: 'Party of 2 (Patricia + husband Richard). DL783 lands 8:45 AM.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverMaria.id, + vehicleId: suburban2.id, // 2 people in 6-seat SUV + }, + }); + + // Dr. Baker (party of 2) + James Whitfield (party of 1) — shared airport pickup + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipDrBaker.id, vipJames.id], + title: 'Airport Pickup — Dr. Baker & Whitfield', + pickupLocation: 'DEN Terminal East, Arrivals Curb', + dropoffLocation: 'Jamboree Camp — VIP Lodge', + startTime: new Date('2026-02-05T11:30:00'), + endTime: new Date('2026-02-05T12:15:00'), + description: 'Shared pickup. Dr. Baker (party 2: + assistant Marcus) lands 10:40 AM. Whitfield (solo) lands 11:30 AM. Wait for both.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverKevin.id, + vehicleId: suburban1.id, // 3 people total in 6-seat SUV + notes: 'Whitfield lands later — coordinate timing. Baker party can wait in VIP lounge.', + }, + }); + + // --- DAY 1: TRANSPORT TO OPENING CEREMONY --- + + // Group shuttle: all VIPs to Opening Ceremony (linked to master event) + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Transport to Opening Ceremony', + pickupLocation: 'VIP Lodge', + dropoffLocation: 'Main Arena — VIP Entrance', + startTime: new Date(jamboreeDay1.getTime() + 9.5 * 60 * 60 * 1000), // 9:30 AM + endTime: new Date(jamboreeDay1.getTime() + 9.75 * 60 * 60 * 1000), // 9:45 AM + description: 'All VIPs to Opening Ceremony. Total party: 9 people (5 VIPs + entourage).', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: whiteVan.id, // 9 people in 14-seat van + masterEventId: openingCeremony.id, + notes: 'Gov. Martinez arriving separately by motorcade.', + }, + }); + + // --- DAY 1: TRANSPORT TO VIP LUNCHEON --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id], + title: 'Transport to VIP Luncheon', + pickupLocation: 'Main Arena — VIP Entrance', + dropoffLocation: 'Eagle Lodge', + startTime: new Date(jamboreeDay1.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM + endTime: new Date(jamboreeDay1.getTime() + 11.75 * 60 * 60 * 1000), // 11:45 AM + description: 'All VIPs + entourage to lunch. Total: 13 people.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: whiteVan.id, // 13 people in 14-seat van — tight! + masterEventId: vipLuncheon.id, + }, + }); + + // --- DAY 1: TRANSPORT TO KEYNOTE --- + + // Two vehicles needed — Gov. Martinez departed, but still 9 people + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id], + title: 'Transport to Keynote (Group A)', + pickupLocation: 'Eagle Lodge', + dropoffLocation: 'Main Arena — VIP Entrance', + startTime: new Date(jamboreeDay1.getTime() + 13.75 * 60 * 60 * 1000), // 1:45 PM + endTime: new Date(jamboreeDay1.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM + description: 'Group A: Roger (3), Patricia (2), James (1) = 6 people', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverMaria.id, + vehicleId: suburban1.id, // 6 people in 6-seat SUV — exactly full + masterEventId: keynoteAddress.id, + }, + }); + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipDrBaker.id, vipSusan.id], + title: 'Transport to Keynote (Group B)', + pickupLocation: 'Eagle Lodge', + dropoffLocation: 'Main Arena — Backstage', + startTime: new Date(jamboreeDay1.getTime() + 13.5 * 60 * 60 * 1000), // 1:30 PM + endTime: new Date(jamboreeDay1.getTime() + 13.75 * 60 * 60 * 1000), // 1:45 PM + description: 'Group B: Dr. Baker (2) + Susan (1) = 3 people. Baker goes backstage early for prep.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverLisa.id, + vehicleId: golfCart1.id, // 3 people in 4-seat golf cart + masterEventId: keynoteAddress.id, + }, + }); + + // --- DAY 1: TRANSPORT TO DONOR MEETING --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipJames.id, vipPatricia.id, vipRoger.id], + title: 'Transport to Donor Meeting', + pickupLocation: 'Main Arena — VIP Entrance', + dropoffLocation: 'Eagle Lodge Conference Room', + startTime: new Date(jamboreeDay1.getTime() + 15.75 * 60 * 60 * 1000), // 3:45 PM + endTime: new Date(jamboreeDay1.getTime() + 16 * 60 * 60 * 1000), // 4:00 PM + description: 'Roger (3) + Patricia (2) + James (1) = 6 people to donor meeting', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverKevin.id, + vehicleId: suburban2.id, + masterEventId: donorMeeting.id, + }, + }); + + // --- DAY 1: TRANSPORT TO CAMPFIRE --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Transport to Campfire Night', + pickupLocation: 'VIP Lodge', + dropoffLocation: 'Campfire Bowl — VIP Section', + startTime: new Date(jamboreeDay1.getTime() + 19.5 * 60 * 60 * 1000), // 7:30 PM + endTime: new Date(jamboreeDay1.getTime() + 19.75 * 60 * 60 * 1000), // 7:45 PM + description: 'All VIPs to campfire. 9 people total.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: whiteVan.id, + masterEventId: campfireNight.id, + }, + }); + + // Return from campfire + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Return from Campfire Night', + pickupLocation: 'Campfire Bowl — VIP Section', + dropoffLocation: 'VIP Lodge', + startTime: new Date(jamboreeDay1.getTime() + 22 * 60 * 60 * 1000), // 10:00 PM + endTime: new Date(jamboreeDay1.getTime() + 22.25 * 60 * 60 * 1000), // 10:15 PM + description: 'Return all VIPs to lodge after campfire.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: whiteVan.id, + masterEventId: campfireNight.id, + }, + }); + + // --- DAY 2: TRANSPORT TO EAGLE SCOUT CEREMONY --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipSusan.id], + title: 'Transport to Eagle Scout Ceremony', + pickupLocation: 'VIP Lodge', + dropoffLocation: 'Main Arena — VIP Entrance', + startTime: new Date(jamboreeDay2.getTime() + 8.5 * 60 * 60 * 1000), // 8:30 AM + endTime: new Date(jamboreeDay2.getTime() + 8.75 * 60 * 60 * 1000), // 8:45 AM + description: 'Roger (3) + Patricia (2) + James (1) + Susan (1) = 7 people. Dr. Baker not attending.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverMaria.id, + vehicleId: whiteVan.id, + masterEventId: eagleScoutCeremony.id, + }, + }); + + // --- DAY 2: TRANSPORT TO FAREWELL BRUNCH --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id], + title: 'Transport to Farewell Brunch', + pickupLocation: 'Main Arena / VIP Lodge', + dropoffLocation: 'Eagle Lodge', + startTime: new Date(jamboreeDay2.getTime() + 11.25 * 60 * 60 * 1000), // 11:15 AM + endTime: new Date(jamboreeDay2.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM + description: 'Final group transport. 9 people total.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverTom.id, + vehicleId: whiteVan.id, + masterEventId: farewellBrunch.id, + }, + }); + + // --- DAY 2: AIRPORT DEPARTURES --- + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipRoger.id], + title: 'Airport Drop-off — Roger Mosby', + pickupLocation: 'VIP Lodge', + dropoffLocation: 'DEN Terminal West', + startTime: new Date(jamboreeDay2.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM + endTime: new Date(jamboreeDay2.getTime() + 15 * 60 * 60 * 1000), // 3:00 PM + description: 'Roger + 2 handlers (3 people) to airport.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverKevin.id, + vehicleId: suburban1.id, + }, + }); + + await prisma.scheduleEvent.create({ + data: { + vipIds: [vipPatricia.id, vipJames.id, vipDrBaker.id], + title: 'Airport Drop-off — Hawkins, Whitfield, Baker', + pickupLocation: 'VIP Lodge', + dropoffLocation: 'DEN Terminal East', + startTime: new Date(jamboreeDay2.getTime() + 14.5 * 60 * 60 * 1000), // 2:30 PM + endTime: new Date(jamboreeDay2.getTime() + 15.5 * 60 * 60 * 1000), // 3:30 PM + description: 'Patricia (2) + James (1) + Dr. Baker (2) = 5 people to airport.', + type: EventType.TRANSPORT, + status: EventStatus.SCHEDULED, + driverId: driverMaria.id, + vehicleId: suburban2.id, // 5 people in 6-seat SUV + }, + }); + + console.log('āœ… Created 15 transport legs linked to master events'); + + // ============================================= + // SUMMARY + // ============================================= + + console.log('\nšŸŽ‰ BSA Jamboree seed data created successfully!\n'); + console.log('VIPs (6):'); + console.log(' Roger Mosby — Chief Scout Exec (party: 3 = VIP + 2 handlers)'); + console.log(' Patricia Hawkins — Board Chair (party: 2 = VIP + spouse)'); + console.log(' James Whitfield III — Major Donor (party: 1 = solo)'); + console.log(' Dr. Angela Baker — Keynote Speaker (party: 2 = VIP + assistant)'); + console.log(' Gov. Carlos Martinez — Governor (party: 4 = VIP + security/aide/advance)'); + console.log(' Susan O\'Malley — Council President (party: 1 = solo)'); + console.log('\nShared Events (7): Opening Ceremony, VIP Luncheon, Keynote, Donor Meeting, Campfire Night, Eagle Scout Ceremony, Farewell Brunch'); + console.log('Transport Legs (15): Airport pickups/dropoffs + shuttles to/from each event'); + console.log('Vehicles (6): 2 Suburbans, 1 Van, 2 Golf Carts, 1 Charter Bus'); + console.log('Drivers (4): Tom Bradley, Maria Gonzalez, Kevin Park, Lisa Chen'); } main()