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:
- "3000:3000"
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
depends_on:
db:
@@ -45,7 +45,7 @@ services:
ports:
- "3001:3001"
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_ADMIN_URL=http://localhost:3001
depends_on:

View File

@@ -15,18 +15,18 @@ model User {
password String
role UserRole @default(VISITOR)
avatar String?
emailVerified Boolean @default(false)
verificationToken String? @unique
resetToken String? @unique
resetTokenExpiry DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
bio String?
location String?
countryId String?
phone String?
isSuspended Boolean @default(false)
suspensionReason String?
countryId String?
resetToken String? @unique
resetTokenExpiry DateTime?
emailVerified Boolean @default(false)
verificationToken String? @unique
businesses Business?
comments Comment[]
conversations ConversationParticipant[]
@@ -40,15 +40,9 @@ model Business {
id String @id @default(uuid())
name String
category String
suggestedCategory String?
location String
countryId String?
city String?
description String
logoUrl String
coverUrl String?
coverPosition String? @default("50% 50%")
coverZoom Float? @default(1.0)
videoUrl String?
contactEmail String
contactPhone String?
@@ -74,38 +68,44 @@ model Business {
isSuspended Boolean @default(false)
suspensionReason String?
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])
comments Comment[]
conversations Conversation[]
offers Offer[]
ratings Rating[]
country Country? @relation(fields: [countryId], references: [id])
categoryRef BusinessCategory? @relation(fields: [categoryId], references: [id])
categoryId String?
}
model BusinessCategory {
id String @id @default(uuid())
name String @unique
slug String @unique
icon String? // Lucide icon name
icon String?
isActive Boolean @default(true)
businesses Business[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
businesses Business[]
}
model Country {
id String @id @default(uuid())
name String @unique
code String @unique // ISO alpha-2
flag String? // Emoji or URL
code String @unique
flag String?
isActive Boolean @default(true)
description String? @db.Text
businesses Business[]
users User[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
description String?
businesses Business[]
users User[]
}
model PricingPlan {
@@ -113,15 +113,15 @@ model PricingPlan {
tier Plan @unique
name String
priceXOF String
yearlyPriceXOF String?
priceEUR String
yearlyPriceEUR String?
description String
features String[]
offerLimit Int @default(1)
recommended Boolean @default(false)
color String @default("gray")
updatedAt DateTime @updatedAt
yearlyPriceEUR String?
yearlyPriceXOF String?
}
model Offer {
@@ -142,23 +142,22 @@ model Offer {
model BlogPost {
id String @id @default(uuid())
title String
slug String? @unique
excerpt String
content String
author String
date DateTime @default(now())
imageUrl String
tags String[] @default([])
metaTitle String?
metaDescription String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
metaDescription String?
metaTitle String?
slug String? @unique
tags String[] @default([])
}
model Interview {
id String @id @default(uuid())
title String
slug String? @unique
guestName String
companyName String
role String
@@ -169,11 +168,12 @@ model Interview {
excerpt String
date DateTime @default(now())
duration String?
tags String[] @default([])
metaTitle String?
metaDescription String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
metaDescription String?
metaTitle String?
slug String? @unique
tags String[] @default([])
}
model Comment {
@@ -194,40 +194,34 @@ model AnalyticsEvent {
label String?
value Float?
metadata Json?
ip String?
country String?
city String?
createdAt DateTime @default(now())
browser String?
os String?
city String?
country String?
device String?
ip String?
os String?
referrer String?
userId String?
createdAt DateTime @default(now())
}
model Rating {
id String @id @default(uuid())
value Int
comment String?
reply String?
replyAt DateTime?
status RatingStatus @default(PENDING)
userId String
businessId String
createdAt DateTime @default(now())
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)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([userId, businessId])
}
enum RatingStatus {
PENDING
APPROVED
REJECTED
}
model Conversation {
id String @id @default(uuid())
businessId String
@@ -272,6 +266,63 @@ model MessageReport {
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 {
PENDING
RESOLVED
@@ -299,54 +350,3 @@ enum InterviewType {
VIDEO
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
}