Modèle de Données : Ajout de la table AnalyticsEvent dans prisma/schema.prisma pour suivre les vues de pages, les clics et le temps de rétention (DWELL_TIME). API Backend : Création de la route app/api/analytics/route.ts pour enregistrer les événements en base de données. Tracking Client : Création du composant AnalyticsTracker.tsx (intégré dans le layout principal) qui capture automatiquement : Le changement de page (Page Views). Les clics sur les boutons et liens importants. Le temps passé sur chaque page. 2. Intégration Base de Données (PostgreSQL/Prisma) Fiches Entreprises : Mise à jour de app/directory/[id]/page.tsx pour récupérer les données réelles depuis PostgreSQL via Prisma au lieu d'utiliser les données de test (mockData). Navigation Dashboard : Correction du bouton "Voir ma fiche" dans le tableau de bord pour qu'il redirige correctement vers le profil public de l'entrepreneur. 3. Administration & Metrics Nouvelle Application Admin : Initialisation d'un dossier admin/ (application Next.js séparée) destinée à la gestion de la plateforme et à la visualisation des statistiques (Metrics & Analytics). 4. Authentification & Inscription Nouvelle Page : Création de app/register/page.tsx pour permettre l'inscription des nouveaux utilisateurs. Gestion de Session : Amélioration de UserProvider.tsx pour une meilleure gestion de l'état utilisateur à travers l'application. 5. Maintenance & Types Mise à jour des types globaux dans types.ts et rafraîchissement du package-lock.json suite à l'ajout de dépendances.
156 lines
4.4 KiB
TypeScript
156 lines
4.4 KiB
TypeScript
import { PrismaClient, UserRole, InterviewType, OfferType } 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';
|
|
|
|
const connectionString = process.env.DATABASE_URL!;
|
|
const pool = new pg.Pool({ connectionString });
|
|
const adapter = new PrismaPg(pool);
|
|
const prisma = new PrismaClient({ adapter });
|
|
|
|
async function main() {
|
|
console.log('🌱 Starting database seeding...');
|
|
|
|
const hashedPassword = await bcrypt.hash('password123', 10);
|
|
|
|
// 1. Clean existing data
|
|
console.log('🧹 Cleaning existing data...');
|
|
await prisma.comment.deleteMany({});
|
|
await prisma.offer.deleteMany({});
|
|
await prisma.business.deleteMany({});
|
|
await prisma.blogPost.deleteMany({});
|
|
await prisma.interview.deleteMany({});
|
|
await prisma.user.deleteMany({});
|
|
|
|
// 2. Create Mock Users
|
|
console.log('👤 Creating users...');
|
|
|
|
// Create Main Admin
|
|
const admin = await prisma.user.create({
|
|
data: {
|
|
name: 'Admin Afropreunariat',
|
|
email: 'admin@afropreunariat.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,
|
|
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!');
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error('❌ Seeding failed:');
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|