/** * Seed script: inserts 75 demo users (mix of roles, ~25 inactive) * Run: node scripts/seed-users.js */ const { PrismaClient } = require('@prisma/client'); const bcrypt = require('bcryptjs'); const prisma = new PrismaClient(); const firstNames = [ 'Liam', 'Olivia', 'Noah', 'Emma', 'James', 'Ava', 'Elijah', 'Sophia', 'Lucas', 'Isabella', 'Mason', 'Mia', 'Logan', 'Charlotte', 'Ethan', 'Amelia', 'Aiden', 'Harper', 'Jackson', 'Evelyn', 'Thabo', 'Zanele', 'Sipho', 'Nomsa', 'Lebo', 'Thandeka', 'Kagiso', 'Palesa', 'Bongani', 'Ayanda', 'Pieter', 'Anri', 'Francois', 'Elizma', 'Hendrik', 'Marius', 'Chloé', 'Dylan', 'Amber', 'Caleb', 'Zoe', 'Hunter', 'Lily', 'Owen', 'Grace', 'Ryan', 'Chloe', 'Nathan', 'Stella', 'Connor', 'Hazel', 'Miles', 'Violet', 'Eli', 'Aurora', 'Isaiah', 'Luna', 'Nolan', 'Scarlett', 'Wyatt', 'Penelope', 'Sebastian', 'Layla', 'Asher', 'Riley', 'Oliver', 'Zoey', 'Ezra', 'Nora', 'Micah', 'Hannah', 'Jonah', 'Leah', 'Aaron', 'Aubrey', 'Charles', ]; const lastNames = [ 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Wilson', 'Moore', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin', 'Thompson', 'Robinson', 'Lewis', 'Dlamini', 'Nkosi', 'Mokoena', 'Ndlovu', 'Mthembu', 'Zulu', 'Nxumalo', 'du Plessis', 'van der Berg', 'Botha', 'Steyn', 'Fourie', 'Pretorius', 'Venter', 'Coetzee', 'van Niekerk', 'Lombard', 'Janse van Rensburg', 'Walker', 'Hall', 'Allen', 'Young', 'Hernandez', 'King', 'Wright', 'Scott', 'Green', 'Baker', 'Adams', 'Nelson', 'Carter', 'Mitchell', 'Perez', 'Roberts', 'Turner', 'Phillips', 'Campbell', 'Parker', 'Evans', 'Edwards', 'Collins', 'Stewart', 'Morris', 'Reed', 'Cook', 'Morgan', ]; function pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; } function randomPhone() { // SA mobile format: 07x/08x xxxxxxx const prefixes = ['071', '072', '073', '074', '076', '078', '079', '081', '082', '083', '084']; return `${pick(prefixes)}${String(Math.floor(Math.random() * 9000000) + 1000000)}`; } async function main() { const passwordHash = await bcrypt.hash('Demo@1234', 10); // Role distribution: ~55 user, ~15 staff, ~5 supervisor const rolePool = [ ...Array(55).fill('user'), ...Array(15).fill('staff'), ...Array(5).fill('supervisor'), ]; const notifPool = ['email', 'email', 'email', 'whatsapp', 'both']; const usedEmails = new Set(); const usedPhones = new Set(); const users = []; // Build 75 user records while (users.length < 75) { const first = pick(firstNames); const last = pick(lastNames); const tag = Math.floor(Math.random() * 999) + 1; const email = `${first.toLowerCase().replace(/ /g, '')}.${last.toLowerCase().replace(/ /g, '').replace(/'/g, '')}${tag}@demo.church`; if (usedEmails.has(email)) continue; usedEmails.add(email); // ~60% of users have a phone number let phone = null; if (Math.random() < 0.6) { let attempt = randomPhone(); let tries = 0; while (usedPhones.has(attempt) && tries < 20) { attempt = randomPhone(); tries++; } if (!usedPhones.has(attempt)) { usedPhones.add(attempt); phone = attempt; } } users.push({ name: `${first} ${last}`, email, password: passwordHash, role: pick(rolePool), isActive: true, // will override 25 below phoneNumber: phone, notificationPreference: pick(notifPool), }); } // Mark exactly 25 as inactive (spread across the list) const inactiveIndexes = new Set(); while (inactiveIndexes.size < 25) { inactiveIndexes.add(Math.floor(Math.random() * 75)); } inactiveIndexes.forEach(i => { users[i].isActive = false; }); console.log(`Inserting ${users.length} users…`); console.log(` Active: ${users.filter(u => u.isActive).length}`); console.log(` Inactive: ${users.filter(u => !u.isActive).length}`); console.log(` Roles: user=${users.filter(u => u.role === 'user').length}, staff=${users.filter(u => u.role === 'staff').length}, supervisor=${users.filter(u => u.role === 'supervisor').length}`); let created = 0; let skipped = 0; for (const user of users) { try { await prisma.user.create({ data: user }); created++; } catch (err) { if (err.code === 'P2002') { skipped++; } else { throw err; } } } console.log(`Done. Created: ${created}, Skipped (duplicate): ${skipped}`); console.log('Default password for all demo users: Demo@1234'); } main() .catch(err => { console.error(err); process.exit(1); }) .finally(() => prisma.$disconnect());