Initial commit: MOPC platform with Docker deployment setup
Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth. Includes production Dockerfile (multi-stage, port 7600), docker-compose with registry-based image pull, Gitea Actions CI workflow, nginx config for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
180
prisma/seed-jury-demo.ts
Normal file
180
prisma/seed-jury-demo.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
async function main() {
|
||||
console.log('Setting up demo jury member...\n')
|
||||
|
||||
// Hash a password for the demo jury account
|
||||
const password = 'JuryDemo2026!'
|
||||
const passwordHash = await bcrypt.hash(password, 12)
|
||||
|
||||
// Create or update jury member
|
||||
const juryUser = await prisma.user.upsert({
|
||||
where: { email: 'jury.demo@monaco-opc.com' },
|
||||
update: {
|
||||
passwordHash,
|
||||
mustSetPassword: false,
|
||||
status: 'ACTIVE',
|
||||
onboardingCompletedAt: new Date(),
|
||||
},
|
||||
create: {
|
||||
email: 'jury.demo@monaco-opc.com',
|
||||
name: 'Dr. Marie Laurent',
|
||||
role: 'JURY_MEMBER',
|
||||
status: 'ACTIVE',
|
||||
passwordHash,
|
||||
mustSetPassword: false,
|
||||
passwordSetAt: new Date(),
|
||||
onboardingCompletedAt: new Date(),
|
||||
expertiseTags: ['Marine Biology', 'Ocean Conservation', 'Sustainable Innovation'],
|
||||
notificationPreference: 'EMAIL',
|
||||
},
|
||||
})
|
||||
|
||||
console.log(`Jury user: ${juryUser.email} (${juryUser.id})`)
|
||||
console.log(`Password: ${password}\n`)
|
||||
|
||||
// Find the round
|
||||
const round = await prisma.round.findFirst({
|
||||
where: { slug: 'mopc-2026-round-1' },
|
||||
})
|
||||
|
||||
if (!round) {
|
||||
console.error('Round not found! Run seed-candidatures first.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`Round: ${round.name} (${round.id})`)
|
||||
|
||||
// Ensure voting window is open
|
||||
const now = new Date()
|
||||
const votingStart = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000) // 7 days ago
|
||||
const votingEnd = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000) // 30 days from now
|
||||
|
||||
await prisma.round.update({
|
||||
where: { id: round.id },
|
||||
data: {
|
||||
status: 'ACTIVE',
|
||||
votingStartAt: votingStart,
|
||||
votingEndAt: votingEnd,
|
||||
},
|
||||
})
|
||||
|
||||
console.log(`Voting window: ${votingStart.toISOString()} → ${votingEnd.toISOString()}\n`)
|
||||
|
||||
// Get some projects to assign
|
||||
const projects = await prisma.project.findMany({
|
||||
where: { roundId: round.id },
|
||||
take: 8,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
select: { id: true, title: true },
|
||||
})
|
||||
|
||||
if (projects.length === 0) {
|
||||
console.error('No projects found! Run seed-candidatures first.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`Found ${projects.length} projects to assign\n`)
|
||||
|
||||
// Create assignments
|
||||
let created = 0
|
||||
let skipped = 0
|
||||
|
||||
for (const project of projects) {
|
||||
try {
|
||||
await prisma.assignment.upsert({
|
||||
where: {
|
||||
userId_projectId_roundId: {
|
||||
userId: juryUser.id,
|
||||
projectId: project.id,
|
||||
roundId: round.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: juryUser.id,
|
||||
projectId: project.id,
|
||||
roundId: round.id,
|
||||
method: 'MANUAL',
|
||||
isRequired: true,
|
||||
},
|
||||
})
|
||||
console.log(` Assigned: ${project.title}`)
|
||||
created++
|
||||
} catch {
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure evaluation criteria exist for this round
|
||||
const existingForm = await prisma.evaluationForm.findFirst({
|
||||
where: { roundId: round.id },
|
||||
})
|
||||
|
||||
if (!existingForm) {
|
||||
await prisma.evaluationForm.create({
|
||||
data: {
|
||||
roundId: round.id,
|
||||
name: 'Round 1 Evaluation',
|
||||
isActive: true,
|
||||
criteriaJson: [
|
||||
{
|
||||
id: 'innovation',
|
||||
label: 'Innovation & Originality',
|
||||
description: 'How innovative is the proposed solution? Does it bring a new approach to ocean conservation?',
|
||||
scale: 10,
|
||||
weight: 25,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'feasibility',
|
||||
label: 'Technical Feasibility',
|
||||
description: 'Is the solution technically viable? Can it be realistically implemented?',
|
||||
scale: 10,
|
||||
weight: 25,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'impact',
|
||||
label: 'Environmental Impact',
|
||||
description: 'What is the potential positive impact on ocean health and marine ecosystems?',
|
||||
scale: 10,
|
||||
weight: 30,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'team',
|
||||
label: 'Team Capability',
|
||||
description: 'Does the team have the skills, experience, and commitment to execute?',
|
||||
scale: 10,
|
||||
weight: 20,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
console.log('\nCreated evaluation form with 4 criteria')
|
||||
} else {
|
||||
console.log('\nEvaluation form already exists')
|
||||
}
|
||||
|
||||
console.log('\n========================================')
|
||||
console.log('Demo jury member setup complete!')
|
||||
console.log(` Email: jury.demo@monaco-opc.com`)
|
||||
console.log(` Password: ${password}`)
|
||||
console.log(` Assignments: ${created} created, ${skipped} skipped`)
|
||||
console.log(` Voting: OPEN (${round.name})`)
|
||||
console.log('========================================\n')
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
Reference in New Issue
Block a user