Files
vip-coordinator/backend/prisma/seed.ts
kyle 74a292ea93 feat: add Help page with search, streamline copilot, misc UI fixes
Adds searchable Help/User Guide page, trims copilot tool bloat,
adds OTHER department option, and various form/layout improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 19:42:39 +01:00

704 lines
26 KiB
TypeScript

import { PrismaClient, Role, Department, ArrivalMode, EventType, EventStatus, VehicleType, VehicleStatus } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
console.log('🌱 Seeding database with BSA Jamboree scenario...');
// Clean up existing data (preserves users/auth accounts)
await prisma.scheduleEvent.deleteMany({});
await prisma.flight.deleteMany({});
await prisma.vehicle.deleteMany({});
// Don't delete drivers linked to users — only standalone test drivers
await prisma.driver.deleteMany({ where: { userId: null } });
await prisma.vIP.deleteMany({});
console.log('✅ Cleared existing test data (preserved user accounts)');
// =============================================
// VEHICLES — BSA Jamboree fleet
// =============================================
const suburban1 = await prisma.vehicle.create({
data: {
name: 'Black Suburban #1',
type: VehicleType.SUV,
licensePlate: 'BSA-001',
seatCapacity: 6,
status: VehicleStatus.AVAILABLE,
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 15-Passenger Van',
type: VehicleType.VAN,
licensePlate: 'BSA-003',
seatCapacity: 14,
status: VehicleStatus.AVAILABLE,
notes: 'Large group transport',
},
});
const golfCart1 = await prisma.vehicle.create({
data: {
name: 'Golf Cart A',
type: VehicleType.GOLF_CART,
licensePlate: 'GC-A',
seatCapacity: 4,
status: VehicleStatus.AVAILABLE,
notes: 'On-site shuttle between venues',
},
});
const golfCart2 = await prisma.vehicle.create({
data: {
name: 'Golf Cart B',
type: VehicleType.GOLF_CART,
licensePlate: 'GC-B',
seatCapacity: 4,
status: VehicleStatus.AVAILABLE,
notes: 'On-site shuttle between venues',
},
});
const charterBus = await prisma.vehicle.create({
data: {
name: 'Charter Bus',
type: VehicleType.BUS,
licensePlate: 'BSA-BUS',
seatCapacity: 45,
status: VehicleStatus.AVAILABLE,
notes: 'Full-size charter for large group moves',
},
});
console.log('✅ Created 6 vehicles');
// =============================================
// DRIVERS
// =============================================
const driverTom = await prisma.driver.create({
data: {
name: 'Tom Bradley',
phone: '+1 (555) 100-0001',
department: Department.ADMIN,
},
});
const driverMaria = await prisma.driver.create({
data: {
name: 'Maria Gonzalez',
phone: '+1 (555) 100-0002',
department: Department.ADMIN,
},
});
const driverKevin = await prisma.driver.create({
data: {
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,
partySize: 3, // Roger + 2 handlers
phone: '+1 (202) 555-0140',
email: 'roger.mosby@scouting.org',
emergencyContactName: 'Linda Mosby',
emergencyContactPhone: '+1 (202) 555-0141',
notes: 'Chief Scout Executive. Travels with 2 staff handlers. Requires accessible vehicle.',
flights: {
create: [
{
flightNumber: 'UA1142',
flightDate: new Date('2026-02-05'),
segment: 1,
departureAirport: 'IAD',
arrivalAirport: 'DEN',
scheduledDeparture: new Date('2026-02-05T07:00:00'),
scheduledArrival: new Date('2026-02-05T09:15:00'),
status: 'scheduled',
},
],
},
},
});
// National Board Chair — travels with spouse
const vipPatricia = await prisma.vIP.create({
data: {
name: 'Patricia Hawkins',
organization: 'BSA National Board',
department: Department.OFFICE_OF_DEVELOPMENT,
arrivalMode: ArrivalMode.FLIGHT,
airportPickup: true,
venueTransport: true,
partySize: 2, // Patricia + spouse
phone: '+1 (404) 555-0230',
email: 'patricia.hawkins@bsaboard.org',
emergencyContactName: 'Richard Hawkins',
emergencyContactPhone: '+1 (404) 555-0231',
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
phone: '+1 (214) 555-0375',
email: 'jwhitfield@whitfieldfoundation.org',
emergencyContactName: 'Catherine Whitfield',
emergencyContactPhone: '+1 (214) 555-0376',
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
phone: '+1 (301) 555-0488',
email: 'abaker@natgeo.com',
emergencyContactName: 'Marcus Webb',
emergencyContactPhone: '+1 (301) 555-0489',
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-05T13:00:00'),
airportPickup: false,
venueTransport: true,
partySize: 4, // Governor + security officer + aide + driver (their own driver stays)
phone: '+1 (303) 555-0100',
email: 'gov.martinez@state.co.us',
emergencyContactName: 'Elena Martinez',
emergencyContactPhone: '+1 (303) 555-0101',
notes: 'Governor arriving by motorcade. Party of 4: Gov, 1 state trooper, 1 aide, 1 advance staff. Their driver does NOT need a seat.',
},
});
// Local Council President — solo, self-driving
const vipSusan = await prisma.vIP.create({
data: {
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,
partySize: 1,
phone: '+1 (720) 555-0550',
email: 'somalley@denvercouncil.org',
emergencyContactName: 'Patrick O\'Malley',
emergencyContactPhone: '+1 (720) 555-0551',
notes: 'Local council president. Knows the venue well. Can help with directions if needed.',
},
});
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: {
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
title: 'Opening Ceremony',
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,
},
});
const vipLuncheon = await prisma.scheduleEvent.create({
data: {
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,
},
});
const keynoteAddress = await prisma.scheduleEvent.create({
data: {
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.',
},
});
const donorMeeting = await prisma.scheduleEvent.create({
data: {
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,
},
});
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,
},
});
// 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()
.catch((e) => {
console.error('❌ Error seeding database:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});