Add unified expertise tag system and round entry notifications
- ExpertiseSelect now fetches tags from database with category grouping - Tags set by admin during invitation are locked and cannot be removed - Onboarding merges user-selected tags with admin-preset tags - MENTOR role now goes through onboarding flow - Added migration for Round.entryNotificationType column - Added seed script with ~90 comprehensive expertise tags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
-- AddRoundEntryNotification
|
||||
-- Adds the entryNotificationType column to Round table for configurable notifications
|
||||
|
||||
ALTER TABLE "Round" ADD COLUMN "entryNotificationType" TEXT;
|
||||
189
prisma/seed-expertise-tags.ts
Normal file
189
prisma/seed-expertise-tags.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Seed script for expertise tags
|
||||
*
|
||||
* Run with: npx tsx prisma/seed-expertise-tags.ts
|
||||
* Or in Docker: docker exec mopc-app npx tsx prisma/seed-expertise-tags.ts
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
interface TagDefinition {
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
color: string
|
||||
}
|
||||
|
||||
const EXPERTISE_TAGS: TagDefinition[] = [
|
||||
// Marine Science & Biology
|
||||
{ name: 'Marine Biology', description: 'Study of marine organisms and ecosystems', category: 'Marine Science', color: '#0ea5e9' },
|
||||
{ name: 'Oceanography', description: 'Physical and chemical properties of the ocean', category: 'Marine Science', color: '#0284c7' },
|
||||
{ name: 'Marine Ecology', description: 'Relationships between marine organisms and environment', category: 'Marine Science', color: '#0891b2' },
|
||||
{ name: 'Fisheries Science', description: 'Management and conservation of fish populations', category: 'Marine Science', color: '#06b6d4' },
|
||||
{ name: 'Marine Microbiology', description: 'Study of microorganisms in marine environments', category: 'Marine Science', color: '#22d3ee' },
|
||||
{ name: 'Marine Genetics', description: 'Genetic research on marine species', category: 'Marine Science', color: '#67e8f9' },
|
||||
{ name: 'Deep Sea Research', description: 'Exploration and study of deep ocean environments', category: 'Marine Science', color: '#164e63' },
|
||||
|
||||
// Conservation & Environment
|
||||
{ name: 'Ocean Conservation', description: 'Protection and preservation of marine environments', category: 'Conservation', color: '#059669' },
|
||||
{ name: 'Biodiversity', description: 'Marine species diversity and protection', category: 'Conservation', color: '#10b981' },
|
||||
{ name: 'Coral Reef Restoration', description: 'Rehabilitation and protection of coral ecosystems', category: 'Conservation', color: '#f97316' },
|
||||
{ name: 'Marine Protected Areas', description: 'Design and management of ocean reserves', category: 'Conservation', color: '#34d399' },
|
||||
{ name: 'Species Conservation', description: 'Protection of endangered marine species', category: 'Conservation', color: '#6ee7b7' },
|
||||
{ name: 'Habitat Restoration', description: 'Rehabilitation of damaged marine habitats', category: 'Conservation', color: '#a7f3d0' },
|
||||
{ name: 'Wildlife Management', description: 'Management of marine wildlife populations', category: 'Conservation', color: '#047857' },
|
||||
|
||||
// Climate & Environment
|
||||
{ name: 'Climate Science', description: 'Ocean-climate interactions and research', category: 'Climate', color: '#14b8a6' },
|
||||
{ name: 'Climate Adaptation', description: 'Strategies for adapting to climate change impacts', category: 'Climate', color: '#2dd4bf' },
|
||||
{ name: 'Climate Mitigation', description: 'Reducing greenhouse gas emissions', category: 'Climate', color: '#5eead4' },
|
||||
{ name: 'Blue Carbon', description: 'Carbon sequestration in marine ecosystems', category: 'Climate', color: '#99f6e4' },
|
||||
{ name: 'Ocean Acidification', description: 'Impact of CO2 on ocean chemistry', category: 'Climate', color: '#0d9488' },
|
||||
{ name: 'Sea Level Rise', description: 'Causes and impacts of rising sea levels', category: 'Climate', color: '#115e59' },
|
||||
|
||||
// Pollution & Waste
|
||||
{ name: 'Plastic Pollution', description: 'Marine plastic waste and solutions', category: 'Pollution', color: '#84cc16' },
|
||||
{ name: 'Waste Management', description: 'Marine and coastal waste solutions', category: 'Pollution', color: '#65a30d' },
|
||||
{ name: 'Microplastics Research', description: 'Study of microplastic impacts', category: 'Pollution', color: '#a3e635' },
|
||||
{ name: 'Chemical Pollution', description: 'Industrial and agricultural runoff', category: 'Pollution', color: '#bef264' },
|
||||
{ name: 'Oil Spill Response', description: 'Prevention and cleanup of oil spills', category: 'Pollution', color: '#4d7c0f' },
|
||||
{ name: 'Water Quality', description: 'Monitoring and improving water quality', category: 'Pollution', color: '#3f6212' },
|
||||
{ name: 'Circular Economy', description: 'Reducing waste through circular systems', category: 'Pollution', color: '#d9f99d' },
|
||||
|
||||
// Sustainable Industries
|
||||
{ name: 'Sustainable Fishing', description: 'Environmentally responsible fishing practices', category: 'Sustainable Industries', color: '#22c55e' },
|
||||
{ name: 'Aquaculture', description: 'Sustainable fish and seafood farming', category: 'Sustainable Industries', color: '#16a34a' },
|
||||
{ name: 'Sustainable Shipping', description: 'Green maritime transportation', category: 'Sustainable Industries', color: '#6366f1' },
|
||||
{ name: 'Sustainable Tourism', description: 'Eco-friendly coastal and marine tourism', category: 'Sustainable Industries', color: '#4f46e5' },
|
||||
{ name: 'Blue Economy', description: 'Sustainable use of ocean resources', category: 'Sustainable Industries', color: '#3b82f6' },
|
||||
{ name: 'Seaweed Industry', description: 'Sustainable seaweed cultivation and products', category: 'Sustainable Industries', color: '#15803d' },
|
||||
{ name: 'Seafood Traceability', description: 'Supply chain transparency in seafood', category: 'Sustainable Industries', color: '#166534' },
|
||||
|
||||
// Technology & Innovation
|
||||
{ name: 'Marine Technology', description: 'Technological solutions for ocean challenges', category: 'Technology', color: '#8b5cf6' },
|
||||
{ name: 'Ocean Robotics', description: 'Autonomous underwater vehicles and drones', category: 'Technology', color: '#7c3aed' },
|
||||
{ name: 'Remote Sensing', description: 'Satellite and sensor-based ocean monitoring', category: 'Technology', color: '#a78bfa' },
|
||||
{ name: 'Data Science', description: 'Ocean data analysis and modeling', category: 'Technology', color: '#c4b5fd' },
|
||||
{ name: 'AI & Machine Learning', description: 'Artificial intelligence for marine research', category: 'Technology', color: '#6d28d9' },
|
||||
{ name: 'Biotechnology', description: 'Marine-derived biotechnology applications', category: 'Technology', color: '#5b21b6' },
|
||||
{ name: 'Sensors & IoT', description: 'Internet of Things for ocean monitoring', category: 'Technology', color: '#4c1d95' },
|
||||
{ name: 'Blockchain', description: 'Distributed ledger for transparency and traceability', category: 'Technology', color: '#ddd6fe' },
|
||||
|
||||
// Energy
|
||||
{ name: 'Renewable Energy', description: 'Marine renewable energy sources', category: 'Energy', color: '#eab308' },
|
||||
{ name: 'Offshore Wind', description: 'Wind energy from offshore installations', category: 'Energy', color: '#ca8a04' },
|
||||
{ name: 'Wave Energy', description: 'Power generation from ocean waves', category: 'Energy', color: '#facc15' },
|
||||
{ name: 'Tidal Energy', description: 'Power generation from tidal movements', category: 'Energy', color: '#fde047' },
|
||||
{ name: 'Ocean Thermal Energy', description: 'OTEC and thermal gradient technologies', category: 'Energy', color: '#a16207' },
|
||||
|
||||
// Policy & Governance
|
||||
{ name: 'Environmental Policy', description: 'Ocean and environmental policy development', category: 'Policy', color: '#a855f7' },
|
||||
{ name: 'International Law', description: 'Law of the sea and maritime regulations', category: 'Policy', color: '#9333ea' },
|
||||
{ name: 'Ocean Governance', description: 'Management and governance of ocean spaces', category: 'Policy', color: '#c084fc' },
|
||||
{ name: 'Regulatory Compliance', description: 'Environmental regulations and compliance', category: 'Policy', color: '#e879f9' },
|
||||
{ name: 'Stakeholder Engagement', description: 'Engaging communities and stakeholders', category: 'Policy', color: '#d946ef' },
|
||||
{ name: 'Advocacy', description: 'Promoting ocean conservation causes', category: 'Policy', color: '#a21caf' },
|
||||
|
||||
// Business & Finance
|
||||
{ name: 'Entrepreneurship', description: 'Ocean-focused startup development', category: 'Business', color: '#f43f5e' },
|
||||
{ name: 'Investment & Finance', description: 'Sustainable ocean investment', category: 'Business', color: '#e11d48' },
|
||||
{ name: 'Impact Investing', description: 'Investment for environmental impact', category: 'Business', color: '#fb7185' },
|
||||
{ name: 'Business Development', description: 'Growing ocean-focused businesses', category: 'Business', color: '#fda4af' },
|
||||
{ name: 'Social Enterprise', description: 'Businesses with social and environmental missions', category: 'Business', color: '#be123c' },
|
||||
{ name: 'Carbon Markets', description: 'Carbon credit trading and blue carbon markets', category: 'Business', color: '#9f1239' },
|
||||
|
||||
// Education & Outreach
|
||||
{ name: 'Education & Outreach', description: 'Ocean literacy and public education', category: 'Education', color: '#ec4899' },
|
||||
{ name: 'Research & Academia', description: 'Academic research and publication', category: 'Education', color: '#db2777' },
|
||||
{ name: 'Citizen Science', description: 'Public participation in scientific research', category: 'Education', color: '#f472b6' },
|
||||
{ name: 'Youth Engagement', description: 'Engaging young people in ocean conservation', category: 'Education', color: '#f9a8d4' },
|
||||
{ name: 'Media & Communications', description: 'Science communication and journalism', category: 'Education', color: '#be185d' },
|
||||
{ name: 'Documentary Filmmaking', description: 'Visual storytelling for ocean conservation', category: 'Education', color: '#9d174d' },
|
||||
|
||||
// Coastal & Community
|
||||
{ name: 'Coastal Management', description: 'Integrated coastal zone management', category: 'Coastal', color: '#f59e0b' },
|
||||
{ name: 'Community Development', description: 'Supporting coastal communities', category: 'Coastal', color: '#d97706' },
|
||||
{ name: 'Small-scale Fisheries', description: 'Supporting artisanal and local fishers', category: 'Coastal', color: '#fbbf24' },
|
||||
{ name: 'Indigenous Knowledge', description: 'Traditional ecological knowledge', category: 'Coastal', color: '#fcd34d' },
|
||||
{ name: 'Disaster Resilience', description: 'Coastal hazard preparedness and response', category: 'Coastal', color: '#b45309' },
|
||||
{ name: 'Mangrove Conservation', description: 'Protection and restoration of mangroves', category: 'Coastal', color: '#92400e' },
|
||||
|
||||
// Specific Focus Areas
|
||||
{ name: 'Arctic & Antarctic', description: 'Polar ocean research and conservation', category: 'Regions', color: '#0369a1' },
|
||||
{ name: 'Mediterranean', description: 'Mediterranean Sea conservation', category: 'Regions', color: '#0c4a6e' },
|
||||
{ name: 'Pacific Islands', description: 'Pacific island marine conservation', category: 'Regions', color: '#075985' },
|
||||
{ name: 'Coral Triangle', description: 'Indo-Pacific coral reef biodiversity', category: 'Regions', color: '#0284c7' },
|
||||
|
||||
// Cross-cutting
|
||||
{ name: 'Project Management', description: 'Managing conservation and research projects', category: 'Skills', color: '#64748b' },
|
||||
{ name: 'Grant Writing', description: 'Securing funding through proposals', category: 'Skills', color: '#475569' },
|
||||
{ name: 'Monitoring & Evaluation', description: 'Measuring project impact and outcomes', category: 'Skills', color: '#334155' },
|
||||
{ name: 'GIS & Mapping', description: 'Geographic information systems for ocean data', category: 'Skills', color: '#1e293b' },
|
||||
{ name: 'Scientific Diving', description: 'Underwater research and data collection', category: 'Skills', color: '#94a3b8' },
|
||||
]
|
||||
|
||||
async function main() {
|
||||
console.log('🏷️ Seeding expertise tags...\n')
|
||||
|
||||
// Get existing tags
|
||||
const existingTags = await prisma.expertiseTag.findMany({
|
||||
select: { name: true },
|
||||
})
|
||||
const existingNames = new Set(existingTags.map((t) => t.name))
|
||||
|
||||
// Filter out tags that already exist
|
||||
const newTags = EXPERTISE_TAGS.filter((t) => !existingNames.has(t.name))
|
||||
|
||||
if (newTags.length === 0) {
|
||||
console.log('✅ All tags already exist in database')
|
||||
return
|
||||
}
|
||||
|
||||
// Get max sort order
|
||||
const maxOrder = await prisma.expertiseTag.aggregate({
|
||||
_max: { sortOrder: true },
|
||||
})
|
||||
const startOrder = (maxOrder._max.sortOrder || 0) + 1
|
||||
|
||||
// Create tags
|
||||
const result = await prisma.expertiseTag.createMany({
|
||||
data: newTags.map((tag, index) => ({
|
||||
name: tag.name,
|
||||
description: tag.description,
|
||||
category: tag.category,
|
||||
color: tag.color,
|
||||
sortOrder: startOrder + index,
|
||||
isActive: true,
|
||||
})),
|
||||
})
|
||||
|
||||
console.log(`✅ Created ${result.count} new expertise tags`)
|
||||
console.log(` Skipped ${existingNames.size} existing tags`)
|
||||
|
||||
// Print summary by category
|
||||
const byCategory = newTags.reduce(
|
||||
(acc, tag) => {
|
||||
acc[tag.category] = (acc[tag.category] || 0) + 1
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, number>
|
||||
)
|
||||
|
||||
console.log('\n📊 Tags created by category:')
|
||||
Object.entries(byCategory)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.forEach(([category, count]) => {
|
||||
console.log(` ${category}: ${count}`)
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('❌ Error seeding expertise tags:', e)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
Reference in New Issue
Block a user