feat: initialize Prisma schema with core business, user, and communication models and configure docker-compose for database deployment
All checks were successful
Build and Push App / build (push) Successful in 8m16s

This commit is contained in:
2026-04-26 23:10:05 +02:00
parent 27b35104b9
commit 792a951e02
2 changed files with 167 additions and 167 deletions

View File

@@ -29,7 +29,7 @@ services:
ports: ports:
- "3000:3000" - "3000:3000"
environment: environment:
- DATABASE_URL=postgresql://admin:adminpassword@db:5432/afropreunariat_dev?schema=public - DATABASE_URL=postgresql://admin:adminpassword@db:5432/afrohub_dev?schema=public
- NEXT_PUBLIC_SITE_URL=http://localhost:3000 - NEXT_PUBLIC_SITE_URL=http://localhost:3000
depends_on: depends_on:
db: db:
@@ -45,7 +45,7 @@ services:
ports: ports:
- "3001:3001" - "3001:3001"
environment: environment:
- DATABASE_URL=postgresql://admin:adminpassword@db:5432/afropreunariat_dev?schema=public - DATABASE_URL=postgresql://admin:adminpassword@db:5432/afrohub_dev?schema=public
- NEXT_PUBLIC_SITE_URL=http://localhost:3000 - NEXT_PUBLIC_SITE_URL=http://localhost:3000
- NEXT_PUBLIC_ADMIN_URL=http://localhost:3001 - NEXT_PUBLIC_ADMIN_URL=http://localhost:3001
depends_on: depends_on:

View File

@@ -15,18 +15,18 @@ model User {
password String password String
role UserRole @default(VISITOR) role UserRole @default(VISITOR)
avatar String? avatar String?
emailVerified Boolean @default(false)
verificationToken String? @unique
resetToken String? @unique
resetTokenExpiry DateTime?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
bio String? bio String?
location String? location String?
countryId String?
phone String? phone String?
isSuspended Boolean @default(false) isSuspended Boolean @default(false)
suspensionReason String? suspensionReason String?
countryId String?
resetToken String? @unique
resetTokenExpiry DateTime?
emailVerified Boolean @default(false)
verificationToken String? @unique
businesses Business? businesses Business?
comments Comment[] comments Comment[]
conversations ConversationParticipant[] conversations ConversationParticipant[]
@@ -40,15 +40,9 @@ model Business {
id String @id @default(uuid()) id String @id @default(uuid())
name String name String
category String category String
suggestedCategory String?
location String location String
countryId String?
city String?
description String description String
logoUrl String logoUrl String
coverUrl String?
coverPosition String? @default("50% 50%")
coverZoom Float? @default(1.0)
videoUrl String? videoUrl String?
contactEmail String contactEmail String
contactPhone String? contactPhone String?
@@ -74,38 +68,44 @@ model Business {
isSuspended Boolean @default(false) isSuspended Boolean @default(false)
suspensionReason String? suspensionReason String?
plan Plan @default(STARTER) plan Plan @default(STARTER)
city String?
countryId String?
coverUrl String?
coverPosition String? @default("50% 50%")
coverZoom Float? @default(1.0)
suggestedCategory String?
categoryId String?
categoryRef BusinessCategory? @relation(fields: [categoryId], references: [id])
country Country? @relation(fields: [countryId], references: [id])
owner User @relation(fields: [ownerId], references: [id]) owner User @relation(fields: [ownerId], references: [id])
comments Comment[] comments Comment[]
conversations Conversation[] conversations Conversation[]
offers Offer[] offers Offer[]
ratings Rating[] ratings Rating[]
country Country? @relation(fields: [countryId], references: [id])
categoryRef BusinessCategory? @relation(fields: [categoryId], references: [id])
categoryId String?
} }
model BusinessCategory { model BusinessCategory {
id String @id @default(uuid()) id String @id @default(uuid())
name String @unique name String @unique
slug String @unique slug String @unique
icon String? // Lucide icon name icon String?
isActive Boolean @default(true) isActive Boolean @default(true)
businesses Business[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
businesses Business[]
} }
model Country { model Country {
id String @id @default(uuid()) id String @id @default(uuid())
name String @unique name String @unique
code String @unique // ISO alpha-2 code String @unique
flag String? // Emoji or URL flag String?
isActive Boolean @default(true) isActive Boolean @default(true)
description String? @db.Text
businesses Business[]
users User[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
description String?
businesses Business[]
users User[]
} }
model PricingPlan { model PricingPlan {
@@ -113,15 +113,15 @@ model PricingPlan {
tier Plan @unique tier Plan @unique
name String name String
priceXOF String priceXOF String
yearlyPriceXOF String?
priceEUR String priceEUR String
yearlyPriceEUR String?
description String description String
features String[] features String[]
offerLimit Int @default(1) offerLimit Int @default(1)
recommended Boolean @default(false) recommended Boolean @default(false)
color String @default("gray") color String @default("gray")
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
yearlyPriceEUR String?
yearlyPriceXOF String?
} }
model Offer { model Offer {
@@ -142,23 +142,22 @@ model Offer {
model BlogPost { model BlogPost {
id String @id @default(uuid()) id String @id @default(uuid())
title String title String
slug String? @unique
excerpt String excerpt String
content String content String
author String author String
date DateTime @default(now()) date DateTime @default(now())
imageUrl String imageUrl String
tags String[] @default([])
metaTitle String?
metaDescription String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
metaDescription String?
metaTitle String?
slug String? @unique
tags String[] @default([])
} }
model Interview { model Interview {
id String @id @default(uuid()) id String @id @default(uuid())
title String title String
slug String? @unique
guestName String guestName String
companyName String companyName String
role String role String
@@ -169,11 +168,12 @@ model Interview {
excerpt String excerpt String
date DateTime @default(now()) date DateTime @default(now())
duration String? duration String?
tags String[] @default([])
metaTitle String?
metaDescription String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
metaDescription String?
metaTitle String?
slug String? @unique
tags String[] @default([])
} }
model Comment { model Comment {
@@ -194,40 +194,34 @@ model AnalyticsEvent {
label String? label String?
value Float? value Float?
metadata Json? metadata Json?
ip String? createdAt DateTime @default(now())
country String?
city String?
browser String? browser String?
os String? city String?
country String?
device String? device String?
ip String?
os String?
referrer String? referrer String?
userId String? userId String?
createdAt DateTime @default(now())
} }
model Rating { model Rating {
id String @id @default(uuid()) id String @id @default(uuid())
value Int value Int
comment String?
reply String?
replyAt DateTime?
status RatingStatus @default(PENDING)
userId String userId String
businessId String businessId String
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade) comment String?
reply String?
replyAt DateTime?
status RatingStatus @default(PENDING)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade) business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([userId, businessId]) @@unique([userId, businessId])
} }
enum RatingStatus {
PENDING
APPROVED
REJECTED
}
model Conversation { model Conversation {
id String @id @default(uuid()) id String @id @default(uuid())
businessId String businessId String
@@ -272,6 +266,63 @@ model MessageReport {
reporter User @relation(fields: [reporterId], references: [id], onDelete: Cascade) reporter User @relation(fields: [reporterId], references: [id], onDelete: Cascade)
} }
model SiteSetting {
id String @id @default("singleton")
siteName String @default("Afrohub")
siteSlogan String @default("La plateforme de référence pour l'entrepreneuriat africain.")
contactEmail String @default("support@afrohub.com")
contactPhone String? @default("+225 00 00 00 00 00")
address String? @default("Abidjan, Côte d'Ivoire")
facebookUrl String?
twitterUrl String?
instagramUrl String?
linkedinUrl String?
footerText String? @default("© 2025 Afrohub. Tous droits réservés.")
updatedAt DateTime @updatedAt
homeBlogCount Int @default(3)
homeBlogShow Boolean @default(true)
homeBlogSubtitle String @default("Toutes les actualités de l'entrepreneuriat africain.")
homeBlogTitle String @default("Derniers Articles")
homeBlogCategories String[] @default([])
homeBlogIds String[] @default([])
homeBlogSelection String @default("latest")
homeCategories String[] @default(["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"])
resetPasswordSubject String @default("Réinitialisation de votre mot de passe - Afrohub")
resetPasswordTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{resetUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Réinitialiser mon mot de passe</a></div><p>Ce lien expirera dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">&copy; 2025 {siteName}. Tous droits réservés.</p></div>")
verifyEmailSubject String @default("Vérification de votre compte - Afrohub")
verifyEmailTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Merci de vous être inscrit sur {siteName}. Pour finaliser la création de votre compte, merci de vérifier votre adresse email en cliquant sur le bouton ci-dessous :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{verifyUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Vérifier mon compte</a></div><p>Si vous n'avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">&copy; 2025 {siteName}. Tous droits réservés.</p></div>")
}
model LegalDocument {
id String @id @default(uuid())
type String @unique
title String
content String
updatedAt DateTime @updatedAt
}
model Event {
id String @id @default(uuid())
title String
description String
date DateTime
location String
thumbnailUrl String
link String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
metaDescription String?
metaTitle String?
slug String? @unique
tags String[] @default([])
}
enum RatingStatus {
PENDING
APPROVED
REJECTED
}
enum ReportStatus { enum ReportStatus {
PENDING PENDING
RESOLVED RESOLVED
@@ -299,54 +350,3 @@ enum InterviewType {
VIDEO VIDEO
ARTICLE ARTICLE
} }
model SiteSetting {
id String @id @default("singleton")
siteName String @default("Afrohub")
siteSlogan String @default("La plateforme de référence pour l'entrepreneuriat africain.")
contactEmail String @default("support@afrohub.com")
contactPhone String? @default("+225 00 00 00 00 00")
address String? @default("Abidjan, Côte d'Ivoire")
facebookUrl String?
twitterUrl String?
instagramUrl String?
linkedinUrl String?
footerText String? @default("© 2025 Afrohub. Tous droits réservés.")
homeBlogShow Boolean @default(true)
homeBlogTitle String @default("Derniers Articles")
homeBlogSubtitle String @default("Toutes les actualités de l'entrepreneuriat africain.")
homeBlogCount Int @default(3)
homeBlogSelection String @default("latest")
homeBlogIds String[] @default([])
homeBlogCategories String[] @default([])
homeCategories String[] @default(["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"])
resetPasswordSubject String @default("Réinitialisation de votre mot de passe - Afrohub")
resetPasswordTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{resetUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Réinitialiser mon mot de passe</a></div><p>Ce lien expirera dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">&copy; 2025 {siteName}. Tous droits réservés.</p></div>") @db.Text
verifyEmailSubject String @default("Vérification de votre compte - Afrohub")
verifyEmailTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Merci de vous être inscrit sur {siteName}. Pour finaliser la création de votre compte, merci de vérifier votre adresse email en cliquant sur le bouton ci-dessous :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{verifyUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Vérifier mon compte</a></div><p>Si vous n'avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">&copy; 2025 {siteName}. Tous droits réservés.</p></div>") @db.Text
updatedAt DateTime @updatedAt
}
model LegalDocument {
id String @id @default(uuid())
type String @unique // 'CGU' or 'CGV'
title String
content String @db.Text
updatedAt DateTime @updatedAt
}
model Event {
id String @id @default(uuid())
title String
slug String? @unique
description String @db.Text
date DateTime
location String
thumbnailUrl String
link String?
tags String[] @default([])
metaTitle String?
metaDescription String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}