feat: add Event interface, implement core Prisma seeding, and create admin categories management page
All checks were successful
Build and Push App / build (push) Successful in 11m4s
All checks were successful
Build and Push App / build (push) Successful in 11m4s
This commit is contained in:
245
prisma/seed.ts
245
prisma/seed.ts
@@ -1,8 +1,11 @@
|
||||
import { PrismaClient, UserRole, InterviewType, OfferType } from '@prisma/client';
|
||||
import { PrismaClient, UserRole, Plan } from '@prisma/client';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
import pg from 'pg';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { MOCK_BUSINESSES, MOCK_BLOG_POSTS, MOCK_INTERVIEWS, MOCK_OFFERS } from '../lib/mockData.js';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config({ path: '.env.local' });
|
||||
dotenv.config();
|
||||
|
||||
const connectionString = process.env.DATABASE_URL!;
|
||||
const pool = new pg.Pool({ connectionString });
|
||||
@@ -10,147 +13,149 @@ const adapter = new PrismaPg(pool);
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Starting database seeding...');
|
||||
console.log('🌱 Starting Core Database Seeding...');
|
||||
const hashedPassword = await bcrypt.hash('afrohub2025', 10);
|
||||
|
||||
const hashedPassword = await bcrypt.hash('password123', 10);
|
||||
|
||||
// 1. Clean existing data
|
||||
// 1. CLEANING DATA
|
||||
console.log('🧹 Cleaning existing data...');
|
||||
// Note: Only clean structure/system tables for a fresh core seed
|
||||
await prisma.rating.deleteMany({});
|
||||
await prisma.comment.deleteMany({});
|
||||
await prisma.offer.deleteMany({});
|
||||
await prisma.business.deleteMany({});
|
||||
await prisma.businessCategory.deleteMany({});
|
||||
await prisma.event.deleteMany({});
|
||||
await prisma.blogPost.deleteMany({});
|
||||
await prisma.interview.deleteMany({});
|
||||
await prisma.pricingPlan.deleteMany({});
|
||||
await prisma.user.deleteMany({});
|
||||
await prisma.country.deleteMany({});
|
||||
|
||||
// 2. Create Mock Users
|
||||
console.log('👤 Creating users...');
|
||||
|
||||
// Create Main Admin
|
||||
const admin = await prisma.user.create({
|
||||
// 2. COUNTRIES
|
||||
console.log('🌍 Seeding countries (Core)...');
|
||||
for (const country of COUNTRIES_DATA) {
|
||||
await prisma.country.create({ data: country });
|
||||
}
|
||||
|
||||
// 3. CATEGORIES
|
||||
console.log('📂 Seeding business categories (Core)...');
|
||||
for (const cat of CATEGORIES_DATA) {
|
||||
await prisma.businessCategory.create({ data: { ...cat, isActive: true } });
|
||||
}
|
||||
|
||||
// 4. PRICING PLANS
|
||||
console.log('💳 Seeding pricing plans (Core)...');
|
||||
for (const plan of PLANS_DATA) {
|
||||
await prisma.pricingPlan.create({ data: plan });
|
||||
}
|
||||
|
||||
// 5. ADMIN USER
|
||||
console.log('👤 Creating main Admin...');
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
name: 'Admin Afrohub',
|
||||
email: 'admin@afrohub.com',
|
||||
password: hashedPassword,
|
||||
role: UserRole.ADMIN,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
// Create Users from mockup (we'll use their ownerId as IDs to match relationships)
|
||||
const usersToCreate = [
|
||||
{ id: 'u1', name: 'Jean-Marc Kouassi', email: 'jm.kouassi@example.com' },
|
||||
{ id: 'u2', name: 'Aïssa Maïga', email: 'aissa@example.com' },
|
||||
{ id: 'u3', name: 'Chidinma Okeke', email: 'chidinma@example.com' },
|
||||
{ id: 'u4', name: 'Ousmane Diop', email: 'ousmane@example.com' },
|
||||
{ id: 'u5', name: 'Marie-Claire Etoa', email: 'marie@example.com' },
|
||||
{ id: 'u6', name: 'David Ochieng', email: 'david@example.com' },
|
||||
{ id: 'u7', name: 'Serge Mbemba', email: 'serge@example.com' },
|
||||
{ id: 'u8', name: 'Fatimata Sylla', email: 'fatimata@example.com' },
|
||||
];
|
||||
|
||||
for (const u of usersToCreate) {
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
email: u.email,
|
||||
password: hashedPassword,
|
||||
role: UserRole.ENTREPRENEUR,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Create Businesses
|
||||
console.log('🏢 Creating businesses...');
|
||||
for (const b of MOCK_BUSINESSES) {
|
||||
await prisma.business.create({
|
||||
data: {
|
||||
id: b.id,
|
||||
name: b.name,
|
||||
slug: b.name.toLowerCase().replace(/[^a-z0-9]/g, '-'),
|
||||
category: b.category,
|
||||
location: b.location,
|
||||
description: b.description,
|
||||
logoUrl: b.logoUrl,
|
||||
videoUrl: b.videoUrl,
|
||||
socialLinks: b.socialLinks as any,
|
||||
contactEmail: b.contactEmail,
|
||||
contactPhone: b.contactPhone,
|
||||
verified: b.verified,
|
||||
viewCount: b.viewCount,
|
||||
rating: b.rating,
|
||||
tags: b.tags,
|
||||
isFeatured: b.isFeatured || false,
|
||||
founderName: b.founderName,
|
||||
founderImageUrl: b.founderImageUrl,
|
||||
keyMetric: b.keyMetric,
|
||||
ownerId: b.ownerId, // This matches the User IDs we just created
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Create Offers
|
||||
console.log('🏷️ Creating offers...');
|
||||
for (const o of MOCK_OFFERS) {
|
||||
await prisma.offer.create({
|
||||
data: {
|
||||
id: o.id,
|
||||
businessId: o.businessId,
|
||||
title: o.title,
|
||||
type: o.type as OfferType,
|
||||
price: o.price,
|
||||
currency: o.currency,
|
||||
description: o.description,
|
||||
imageUrl: o.imageUrl,
|
||||
active: o.active,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 5. Create Blog Posts
|
||||
console.log('✍️ Creating blog posts...');
|
||||
for (const p of MOCK_BLOG_POSTS) {
|
||||
await prisma.blogPost.create({
|
||||
data: {
|
||||
id: p.id,
|
||||
title: p.title,
|
||||
excerpt: p.excerpt,
|
||||
content: p.content,
|
||||
author: p.author,
|
||||
imageUrl: p.imageUrl,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 6. Create Interviews
|
||||
console.log('🎙️ Creating interviews...');
|
||||
for (const i of MOCK_INTERVIEWS) {
|
||||
await prisma.interview.create({
|
||||
data: {
|
||||
id: i.id,
|
||||
title: i.title,
|
||||
guestName: i.guestName,
|
||||
companyName: i.companyName,
|
||||
role: i.role,
|
||||
type: i.type as InterviewType,
|
||||
thumbnailUrl: i.thumbnailUrl,
|
||||
videoUrl: i.videoUrl,
|
||||
content: i.content,
|
||||
excerpt: i.excerpt,
|
||||
duration: i.duration,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log('✅ Seeding completed successfully!');
|
||||
console.log('✅ CORE SEED COMPLETED SUCCESSFULLY!');
|
||||
console.log('💡 Note: Use seed-30.ts and seed-events.ts for mockup data.');
|
||||
}
|
||||
|
||||
// --- CORE DATA ---
|
||||
|
||||
const CATEGORIES_DATA = [
|
||||
{ name: "Technologie & IT", slug: "technologie-it" },
|
||||
{ name: "Agriculture & Agrobusiness", slug: "agriculture-agrobusiness" },
|
||||
{ name: "Mode & Textile", slug: "mode-textile" },
|
||||
{ name: "Cosmétique & Beauté", slug: "cosmetique-beaute" },
|
||||
{ name: "Services aux entreprises", slug: "services-entreprises" },
|
||||
{ name: "Restauration & Alimentation", slug: "restauration-alimentation" },
|
||||
{ name: "Construction & BTP", slug: "construction-btp" },
|
||||
{ name: "Éducation & Formation", slug: "education-formation" },
|
||||
{ name: "Santé & Bien-être", slug: "sante-bien-etre" },
|
||||
{ name: "Artisanat & Déco", slug: "artisanat-deco" },
|
||||
{ name: "Tourisme & Loisirs", slug: "tourisme-loisirs" },
|
||||
{ name: "Finance & Assurance", slug: "finance-assurance" }
|
||||
];
|
||||
|
||||
const PLANS_DATA = [
|
||||
{
|
||||
tier: Plan.STARTER,
|
||||
name: 'Starter',
|
||||
priceXOF: 'Gratuit',
|
||||
yearlyPriceXOF: 'Gratuit',
|
||||
priceEUR: '0€',
|
||||
yearlyPriceEUR: '0€',
|
||||
description: 'Pour démarrer votre présence en ligne.',
|
||||
features: ['Fiche entreprise basique', 'Visible dans la recherche', '1 Offre produit/service', 'Support par email'],
|
||||
offerLimit: 1,
|
||||
recommended: false,
|
||||
color: 'gray'
|
||||
},
|
||||
{
|
||||
tier: Plan.BOOSTER,
|
||||
name: 'Booster',
|
||||
priceXOF: '3 500 FCFA',
|
||||
yearlyPriceXOF: '33 500 FCFA',
|
||||
priceEUR: '5€',
|
||||
yearlyPriceEUR: '48€',
|
||||
description: "L'indispensable pour les entreprises en croissance.",
|
||||
features: ['Tout du plan Starter', 'Badge "Vérifié" ✅', 'Jusqu\'à 10 Offres produits', 'Lien vers réseaux sociaux & Site Web', 'Statistiques de base (Vues)'],
|
||||
offerLimit: 10,
|
||||
recommended: true,
|
||||
color: 'brand'
|
||||
},
|
||||
{
|
||||
tier: Plan.EMPIRE,
|
||||
name: 'Empire',
|
||||
priceXOF: '13 000 FCFA',
|
||||
yearlyPriceXOF: '125 000 FCFA',
|
||||
priceEUR: '20€',
|
||||
yearlyPriceEUR: '192€',
|
||||
description: 'Dominez votre marché avec une visibilité maximale.',
|
||||
features: ['Tout du plan Booster', 'Badge "Recommandé" 🏆', 'Offres illimitées', 'Intégration vidéo Youtube', 'Interview écrite sur le Blog', 'Support prioritaire WhatsApp'],
|
||||
offerLimit: 1000,
|
||||
recommended: false,
|
||||
color: 'amber'
|
||||
}
|
||||
];
|
||||
|
||||
const COUNTRIES_DATA = [
|
||||
{ name: "Bénin", code: "BJ", flag: "🇧🇯" },
|
||||
{ name: "Burkina Faso", code: "BF", flag: "🇧🇫" },
|
||||
{ name: "Cameroun", code: "CM", flag: "🇨🇲" },
|
||||
{ name: "Congo-Kinshasa", code: "CD", flag: "🇨🇩" },
|
||||
{ name: "Côte d'Ivoire", code: "CI", flag: "🇨🇮" },
|
||||
{ name: "France", code: "FR", flag: "🇫🇷" },
|
||||
{ name: "Belgique", code: "BE", flag: "🇧🇪" },
|
||||
{ name: "Suisse", code: "CH", flag: "🇨🇭" },
|
||||
{ name: "Luxembourg", code: "LU", flag: "🇱🇺" },
|
||||
{ name: "Allemagne", code: "DE", flag: "🇩🇪" },
|
||||
{ name: "Italie", code: "IT", flag: "🇮🇹" },
|
||||
{ name: "Espagne", code: "ES", flag: "🇪🇸" },
|
||||
{ name: "Portugal", code: "PT", flag: "🇵🇹" },
|
||||
{ name: "Royaume-Uni", code: "GB", flag: "🇬🇧" },
|
||||
{ name: "Pays-Bas", code: "NL", flag: "🇳🇱" },
|
||||
{ name: "Gabon", code: "GA", flag: "🇬🇦" },
|
||||
{ name: "Ghana", code: "GH", flag: "🇬🇭" },
|
||||
{ name: "Guinée", code: "GN", flag: "🇬🇳" },
|
||||
{ name: "Mali", code: "ML", flag: "🇲🇱" },
|
||||
{ name: "Maroc", code: "MA", flag: "🇲🇦" },
|
||||
{ name: "Niger", code: "NE", flag: "🇳🇪" },
|
||||
{ name: "Nigéria", code: "NG", flag: "🇳🇬" },
|
||||
{ name: "Sénégal", code: "SN", flag: "🇸🇳" },
|
||||
{ name: "Togo", code: "TG", flag: "🇹🇬" }
|
||||
];
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('❌ Seeding failed:');
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
await pool.end();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user