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

This commit is contained in:
2026-04-24 14:39:01 +02:00
parent 11678e0b33
commit 3c58e60b33
12 changed files with 176 additions and 592 deletions

View File

@@ -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();
});