178 lines
7.3 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
const prisma = new PrismaClient();
async function main() {
console.log('🦉 Seeding Owl Stream database...');
// Admin user
const adminHash = await bcrypt.hash('admin1234', 12);
const admin = await prisma.user.upsert({
where: { email: 'admin@owlwatch.org' },
update: {},
create: { email: 'admin@owlwatch.org', name: 'Admin User', role: 'admin', password_hash: adminHash },
});
// Volunteer user
const volHash = await bcrypt.hash('volunteer1234', 12);
const volunteer = await prisma.user.upsert({
where: { email: 'vol@owlwatch.org' },
update: {},
create: { email: 'vol@owlwatch.org', name: 'Jane Volunteer', role: 'volunteer', password_hash: volHash },
});
// Donor user
const donorHash = await bcrypt.hash('donor1234', 12);
await prisma.user.upsert({
where: { email: 'donor@example.com' },
update: {},
create: { email: 'donor@example.com', name: 'Bob Donor', role: 'donor', password_hash: donorHash },
});
// 10 Burrows (Cape Coral GPS coordinates)
const burrowData = [
{ gps_lat: 26.5629, gps_lng: -81.9495, location_description: 'Burnt Store Rd median' },
{ gps_lat: 26.5814, gps_lng: -81.9631, location_description: 'Rotary Park entrance' },
{ gps_lat: 26.5677, gps_lng: -81.9712, location_description: 'Veterans Pkwy near Agualinda' },
{ gps_lat: 26.5532, gps_lng: -81.9589, location_description: 'Cape Coral Pkwy & Del Prado' },
{ gps_lat: 26.5901, gps_lng: -81.9444, location_description: 'Four Mile Cove Ecological Preserve' },
{ gps_lat: 26.5743, gps_lng: -81.9822, location_description: 'Yellow Fever Creek Greenway' },
{ gps_lat: 26.5465, gps_lng: -81.9367, location_description: 'Cape Harbour Marina' },
{ gps_lat: 26.6012, gps_lng: -81.9555, location_description: 'Matlacha Pass Aquatic Preserve edge' },
{ gps_lat: 26.5788, gps_lng: -82.0011, location_description: 'Camelot Island access' },
{ gps_lat: 26.5620, gps_lng: -81.9198, location_description: 'SE 46th Ln vacant lot' },
];
for (const b of burrowData) {
await prisma.burrow.create({
data: { ...b, status: 'active', assigned_volunteer_id: volunteer.id },
});
}
// 3 Livestream Sources
await prisma.livestreamSource.createMany({
data: [
{
name: 'Rotary Park Cam A',
stream_url: 'https://stream.owlwatch.org/live/rotary-a',
camera_location: 'Rotary Park, Cape Coral FL',
status: 'live',
thumbnail_url: 'https://stream.owlwatch.org/thumbs/rotary-a.jpg',
},
{
name: 'Burnt Store Rd Nest',
stream_url: 'https://stream.owlwatch.org/live/burnt-store',
camera_location: 'Burnt Store Rd, Cape Coral FL',
status: 'live',
thumbnail_url: 'https://stream.owlwatch.org/thumbs/burnt-store.jpg',
},
{
name: 'Veterans Pkwy Cam',
stream_url: 'https://stream.owlwatch.org/live/veterans',
camera_location: 'Veterans Pkwy, Cape Coral FL',
status: 'offline',
thumbnail_url: 'https://stream.owlwatch.org/thumbs/veterans.jpg',
},
],
skipDuplicates: true,
});
// 5 Events
const events = [
{
title: 'Morning Burrow Count — Spring Survey',
description: 'Volunteer survey of all known burrow sites. Meet at Rotary Park 7am.',
date: new Date('2026-03-15T07:00:00'),
location: 'Rotary Park, Cape Coral',
max_attendees: 30,
type: 'cleanup' as const,
},
{
title: 'Burrowing Owl Awareness Day',
description: 'Educational fair at Cape Coral City Hall. Bring the family!',
date: new Date('2026-03-22T10:00:00'),
location: 'Cape Coral City Hall',
max_attendees: 200,
type: 'educational' as const,
},
{
title: 'Night Camera Installation',
description: 'Volunteers needed to help install night vision cameras at high-activity burrow sites.',
date: new Date('2026-04-05T17:30:00'),
location: 'Veterans Pkwy Site, Cape Coral',
max_attendees: 10,
type: 'cleanup' as const,
},
{
title: 'Owl Fest Fundraiser Dinner',
description: 'Annual fundraiser dinner. Tickets include 3-course dinner and owl cam raffle.',
date: new Date('2026-04-19T18:00:00'),
location: 'Cape Coral Yacht Club',
max_attendees: 150,
type: 'fundraiser' as const,
},
{
title: 'Habitat Restoration — Camelot Island',
description: 'Remove invasive species around burrow zones. Gloves and tools provided.',
date: new Date('2026-05-03T08:00:00'),
location: 'Camelot Island, Cape Coral',
max_attendees: 40,
type: 'cleanup' as const,
},
];
for (const e of events) {
await prisma.event.create({ data: e });
}
// Sample wildlife sightings
const sightings = [
{ species: 'Burrowing Owl (Athene cunicularia)', gps_lat: 26.5629, gps_lng: -81.9495, description: 'Pair spotted at entrance burrow, chick visible', verified: true },
{ species: 'Florida Sandhill Crane', gps_lat: 26.5814, gps_lng: -81.9631, description: 'Family of 3 near Rotary Park pond', verified: false },
{ species: 'Osprey', gps_lat: 26.5901, gps_lng: -81.9444, description: 'Nesting on channel marker', verified: true },
{ species: 'Burrowing Owl (Athene cunicularia)', gps_lat: 26.5788, gps_lng: -82.0011, description: 'Single owl standing guard at burrow', verified: true },
{ species: 'Gopher Tortoise', gps_lat: 26.5532, gps_lng: -81.9589, description: 'Near burrow site 4, likely co-habiting', verified: false },
];
for (const s of sightings) {
await prisma.wildlifeSighting.create({
data: { ...s, reporter_id: volunteer.id },
});
}
// Volunteer hours
await prisma.volunteerHour.createMany({
data: [
{ volunteer_id: volunteer.id, date: new Date('2026-02-10'), hours: 4, task_description: 'Morning burrow survey, Burnt Store Rd section', verified_by: admin.id },
{ volunteer_id: volunteer.id, date: new Date('2026-02-15'), hours: 2.5, task_description: 'Camera check and data upload', verified_by: admin.id },
{ volunteer_id: volunteer.id, date: new Date('2026-02-18'), hours: 6, task_description: 'Educational booth at Cape Coral Farmers Market' },
],
});
// Equipment items
await prisma.equipmentItem.createMany({
data: [
{ name: 'Nikon P950 Spotting Camera', description: '83x optical zoom for burrow photography', status: 'available' },
{ name: 'Trail Camera x4 Pack', description: 'Browning night vision trail cams', status: 'checked_out', checked_out_by: volunteer.id, checked_out_at: new Date() },
{ name: 'GPS Unit — Garmin eTrex 32x', description: 'For precise burrow coordinate logging', status: 'available' },
{ name: 'Binoculars — Vortex Viper 10x42', description: 'Shared pair for volunteer surveys', status: 'available' },
{ name: 'First Aid Kit (Field)', description: 'Standard field kit, check quarterly', status: 'available' },
],
});
// Sample donation
await prisma.donation.create({
data: { amount: 250, campaign: 'land_preservation', stripe_payment_id: 'pi_seed_001' },
});
console.log('✅ Seeding complete!');
console.log(' Admin: admin@owlwatch.org / admin1234');
console.log(' Volunteer: vol@owlwatch.org / volunteer1234');
console.log(' Donor: donor@example.com / donor1234');
}
main()
.catch(console.error)
.finally(() => prisma.$disconnect());