diff --git a/admin/package.json b/admin/package.json
index 05e45ad..226abcf 100644
--- a/admin/package.json
+++ b/admin/package.json
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev",
- "build": "prisma generate && next build",
+ "build": "prisma generate --schema=../prisma/schema.prisma && next build",
"start": "next start -p 3000",
"lint": "eslint"
},
@@ -43,4 +43,4 @@
"tailwindcss": "^4",
"typescript": "^5"
}
-}
+}
\ No newline at end of file
diff --git a/admin/prisma/migrations/0_init/migration.sql b/admin/prisma/migrations/0_init/migration.sql
deleted file mode 100644
index d14cf34..0000000
Binary files a/admin/prisma/migrations/0_init/migration.sql and /dev/null differ
diff --git a/admin/prisma/migrations/20260427214502_init/migration.sql b/admin/prisma/migrations/20260427214502_init/migration.sql
deleted file mode 100644
index 220c22c..0000000
--- a/admin/prisma/migrations/20260427214502_init/migration.sql
+++ /dev/null
@@ -1,459 +0,0 @@
--- CreateEnum
-CREATE TYPE "RatingStatus" AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
-
--- CreateEnum
-CREATE TYPE "ReportStatus" AS ENUM ('PENDING', 'RESOLVED', 'DISMISSED');
-
--- CreateEnum
-CREATE TYPE "UserRole" AS ENUM ('VISITOR', 'ENTREPRENEUR', 'ADMIN');
-
--- CreateEnum
-CREATE TYPE "Plan" AS ENUM ('STARTER', 'BOOSTER', 'EMPIRE');
-
--- CreateEnum
-CREATE TYPE "OfferType" AS ENUM ('PRODUCT', 'SERVICE');
-
--- CreateEnum
-CREATE TYPE "InterviewType" AS ENUM ('VIDEO', 'ARTICLE');
-
--- CreateTable
-CREATE TABLE "User" (
- "id" TEXT NOT NULL,
- "name" TEXT NOT NULL,
- "email" TEXT NOT NULL,
- "password" TEXT NOT NULL,
- "role" "UserRole" NOT NULL DEFAULT 'VISITOR',
- "avatar" TEXT,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "bio" TEXT,
- "location" TEXT,
- "phone" TEXT,
- "isSuspended" BOOLEAN NOT NULL DEFAULT false,
- "suspensionReason" TEXT,
- "countryId" TEXT,
- "resetToken" TEXT,
- "resetTokenExpiry" TIMESTAMP(3),
- "emailVerified" BOOLEAN NOT NULL DEFAULT false,
- "verificationToken" TEXT,
-
- CONSTRAINT "User_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Business" (
- "id" TEXT NOT NULL,
- "name" TEXT NOT NULL,
- "category" TEXT NOT NULL,
- "location" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "logoUrl" TEXT NOT NULL,
- "videoUrl" TEXT,
- "contactEmail" TEXT NOT NULL,
- "contactPhone" TEXT,
- "socialLinks" JSONB,
- "verified" BOOLEAN NOT NULL DEFAULT false,
- "viewCount" INTEGER NOT NULL DEFAULT 0,
- "rating" DOUBLE PRECISION NOT NULL DEFAULT 0.0,
- "ratingCount" INTEGER NOT NULL DEFAULT 0,
- "tags" TEXT[],
- "isFeatured" BOOLEAN NOT NULL DEFAULT false,
- "founderName" TEXT,
- "founderImageUrl" TEXT,
- "keyMetric" TEXT,
- "ownerId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "slug" TEXT,
- "isActive" BOOLEAN NOT NULL DEFAULT false,
- "showEmail" BOOLEAN NOT NULL DEFAULT true,
- "showPhone" BOOLEAN NOT NULL DEFAULT true,
- "showSocials" BOOLEAN NOT NULL DEFAULT true,
- "websiteUrl" TEXT,
- "isSuspended" BOOLEAN NOT NULL DEFAULT false,
- "suspensionReason" TEXT,
- "plan" "Plan" NOT NULL DEFAULT 'STARTER',
- "city" TEXT,
- "countryId" TEXT,
- "coverUrl" TEXT,
- "coverPosition" TEXT DEFAULT '50% 50%',
- "coverZoom" DOUBLE PRECISION DEFAULT 1.0,
- "suggestedCategory" TEXT,
- "categoryId" TEXT,
-
- CONSTRAINT "Business_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "BusinessCategory" (
- "id" TEXT NOT NULL,
- "name" TEXT NOT NULL,
- "slug" TEXT NOT NULL,
- "icon" TEXT,
- "isActive" BOOLEAN NOT NULL DEFAULT true,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
-
- CONSTRAINT "BusinessCategory_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Country" (
- "id" TEXT NOT NULL,
- "name" TEXT NOT NULL,
- "code" TEXT NOT NULL,
- "flag" TEXT,
- "isActive" BOOLEAN NOT NULL DEFAULT true,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "description" TEXT,
-
- CONSTRAINT "Country_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "PricingPlan" (
- "id" TEXT NOT NULL,
- "tier" "Plan" NOT NULL,
- "name" TEXT NOT NULL,
- "priceXOF" TEXT NOT NULL,
- "priceEUR" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "features" TEXT[],
- "offerLimit" INTEGER NOT NULL DEFAULT 1,
- "recommended" BOOLEAN NOT NULL DEFAULT false,
- "color" TEXT NOT NULL DEFAULT 'gray',
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "yearlyPriceEUR" TEXT,
- "yearlyPriceXOF" TEXT,
-
- CONSTRAINT "PricingPlan_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Offer" (
- "id" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "type" "OfferType" NOT NULL,
- "price" DOUBLE PRECISION NOT NULL,
- "currency" TEXT NOT NULL DEFAULT 'XOF',
- "description" TEXT,
- "imageUrl" TEXT NOT NULL,
- "active" BOOLEAN NOT NULL DEFAULT true,
- "businessId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
-
- CONSTRAINT "Offer_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "BlogPost" (
- "id" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "excerpt" TEXT NOT NULL,
- "content" TEXT NOT NULL,
- "author" TEXT NOT NULL,
- "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "imageUrl" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "metaDescription" TEXT,
- "metaTitle" TEXT,
- "slug" TEXT,
- "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
-
- CONSTRAINT "BlogPost_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Interview" (
- "id" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "guestName" TEXT NOT NULL,
- "companyName" TEXT NOT NULL,
- "role" TEXT NOT NULL,
- "type" "InterviewType" NOT NULL,
- "thumbnailUrl" TEXT NOT NULL,
- "videoUrl" TEXT,
- "content" TEXT,
- "excerpt" TEXT NOT NULL,
- "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "duration" TEXT,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "metaDescription" TEXT,
- "metaTitle" TEXT,
- "slug" TEXT,
- "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
-
- CONSTRAINT "Interview_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Comment" (
- "id" TEXT NOT NULL,
- "content" TEXT NOT NULL,
- "authorId" TEXT NOT NULL,
- "businessId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
-
- CONSTRAINT "Comment_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "AnalyticsEvent" (
- "id" TEXT NOT NULL,
- "type" TEXT NOT NULL,
- "path" TEXT NOT NULL,
- "label" TEXT,
- "value" DOUBLE PRECISION,
- "metadata" JSONB,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "browser" TEXT,
- "city" TEXT,
- "country" TEXT,
- "device" TEXT,
- "ip" TEXT,
- "os" TEXT,
- "referrer" TEXT,
- "userId" TEXT,
-
- CONSTRAINT "AnalyticsEvent_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Rating" (
- "id" TEXT NOT NULL,
- "value" INTEGER NOT NULL,
- "userId" TEXT NOT NULL,
- "businessId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "comment" TEXT,
- "reply" TEXT,
- "replyAt" TIMESTAMP(3),
- "status" "RatingStatus" NOT NULL DEFAULT 'PENDING',
-
- CONSTRAINT "Rating_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Conversation" (
- "id" TEXT NOT NULL,
- "businessId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
-
- CONSTRAINT "Conversation_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "ConversationParticipant" (
- "id" TEXT NOT NULL,
- "userId" TEXT NOT NULL,
- "conversationId" TEXT NOT NULL,
- "isArchived" BOOLEAN NOT NULL DEFAULT false,
-
- CONSTRAINT "ConversationParticipant_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Message" (
- "id" TEXT NOT NULL,
- "content" TEXT NOT NULL,
- "senderId" TEXT NOT NULL,
- "conversationId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "read" BOOLEAN NOT NULL DEFAULT false,
-
- CONSTRAINT "Message_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "MessageReport" (
- "id" TEXT NOT NULL,
- "reason" TEXT,
- "messageId" TEXT NOT NULL,
- "reporterId" TEXT NOT NULL,
- "status" "ReportStatus" NOT NULL DEFAULT 'PENDING',
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
-
- CONSTRAINT "MessageReport_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "SiteSetting" (
- "id" TEXT NOT NULL DEFAULT 'singleton',
- "siteName" TEXT NOT NULL DEFAULT 'Afrohub',
- "siteSlogan" TEXT NOT NULL DEFAULT 'La plateforme de référence pour l''entrepreneuriat africain.',
- "contactEmail" TEXT NOT NULL DEFAULT 'support@afrohub.com',
- "contactPhone" TEXT DEFAULT '+225 00 00 00 00 00',
- "address" TEXT DEFAULT 'Abidjan, Côte d''Ivoire',
- "facebookUrl" TEXT,
- "twitterUrl" TEXT,
- "instagramUrl" TEXT,
- "linkedinUrl" TEXT,
- "footerText" TEXT DEFAULT '© 2025 Afrohub. Tous droits réservés.',
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "homeBlogCount" INTEGER NOT NULL DEFAULT 3,
- "homeBlogShow" BOOLEAN NOT NULL DEFAULT true,
- "homeBlogSubtitle" TEXT NOT NULL DEFAULT 'Toutes les actualités de l''entrepreneuriat africain.',
- "homeBlogTitle" TEXT NOT NULL DEFAULT 'Derniers Articles',
- "homeBlogCategories" TEXT[] DEFAULT ARRAY[]::TEXT[],
- "homeBlogIds" TEXT[] DEFAULT ARRAY[]::TEXT[],
- "homeBlogSelection" TEXT NOT NULL DEFAULT 'latest',
- "homeCategories" TEXT[] DEFAULT ARRAY['Technologie & IT', 'Agriculture & Agrobusiness', 'Mode & Textile', 'Cosmétique & Beauté']::TEXT[],
- "resetPasswordSubject" TEXT NOT NULL DEFAULT 'Réinitialisation de votre mot de passe - Afrohub',
- "resetPasswordTemplate" TEXT NOT NULL DEFAULT '
{siteName}
Bonjour {name},
Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :
Ce lien expirera dans 1 heure. Si vous n''avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.
© 2025 {siteName}. Tous droits réservés.
',
- "verifyEmailSubject" TEXT NOT NULL DEFAULT 'Vérification de votre compte - Afrohub',
- "verifyEmailTemplate" TEXT NOT NULL DEFAULT '{siteName}
Bonjour {name},
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 :
Si vous n''avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.
© 2025 {siteName}. Tous droits réservés.
',
-
- CONSTRAINT "SiteSetting_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "LegalDocument" (
- "id" TEXT NOT NULL,
- "type" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "content" TEXT NOT NULL,
- "updatedAt" TIMESTAMP(3) NOT NULL,
-
- CONSTRAINT "LegalDocument_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Event" (
- "id" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "date" TIMESTAMP(3) NOT NULL,
- "location" TEXT NOT NULL,
- "thumbnailUrl" TEXT NOT NULL,
- "link" TEXT,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" TIMESTAMP(3) NOT NULL,
- "metaDescription" TEXT,
- "metaTitle" TEXT,
- "slug" TEXT,
- "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
-
- CONSTRAINT "Event_pkey" PRIMARY KEY ("id")
-);
-
--- CreateTable
-CREATE TABLE "Favorite" (
- "id" TEXT NOT NULL,
- "userId" TEXT NOT NULL,
- "businessId" TEXT NOT NULL,
- "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
-
- CONSTRAINT "Favorite_pkey" PRIMARY KEY ("id")
-);
-
--- CreateIndex
-CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-
--- CreateIndex
-CREATE UNIQUE INDEX "User_resetToken_key" ON "User"("resetToken");
-
--- CreateIndex
-CREATE UNIQUE INDEX "User_verificationToken_key" ON "User"("verificationToken");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Business_ownerId_key" ON "Business"("ownerId");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Business_slug_key" ON "Business"("slug");
-
--- CreateIndex
-CREATE UNIQUE INDEX "BusinessCategory_name_key" ON "BusinessCategory"("name");
-
--- CreateIndex
-CREATE UNIQUE INDEX "BusinessCategory_slug_key" ON "BusinessCategory"("slug");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Country_name_key" ON "Country"("name");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Country_code_key" ON "Country"("code");
-
--- CreateIndex
-CREATE UNIQUE INDEX "PricingPlan_tier_key" ON "PricingPlan"("tier");
-
--- CreateIndex
-CREATE UNIQUE INDEX "BlogPost_slug_key" ON "BlogPost"("slug");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Interview_slug_key" ON "Interview"("slug");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Rating_userId_businessId_key" ON "Rating"("userId", "businessId");
-
--- CreateIndex
-CREATE UNIQUE INDEX "ConversationParticipant_userId_conversationId_key" ON "ConversationParticipant"("userId", "conversationId");
-
--- CreateIndex
-CREATE UNIQUE INDEX "LegalDocument_type_key" ON "LegalDocument"("type");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Event_slug_key" ON "Event"("slug");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Favorite_userId_businessId_key" ON "Favorite"("userId", "businessId");
-
--- AddForeignKey
-ALTER TABLE "User" ADD CONSTRAINT "User_countryId_fkey" FOREIGN KEY ("countryId") REFERENCES "Country"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Business" ADD CONSTRAINT "Business_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "BusinessCategory"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Business" ADD CONSTRAINT "Business_countryId_fkey" FOREIGN KEY ("countryId") REFERENCES "Country"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Business" ADD CONSTRAINT "Business_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Offer" ADD CONSTRAINT "Offer_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "Business"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Comment" ADD CONSTRAINT "Comment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Comment" ADD CONSTRAINT "Comment_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "Business"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Rating" ADD CONSTRAINT "Rating_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "Business"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Rating" ADD CONSTRAINT "Rating_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Conversation" ADD CONSTRAINT "Conversation_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "Business"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "ConversationParticipant" ADD CONSTRAINT "ConversationParticipant_conversationId_fkey" FOREIGN KEY ("conversationId") REFERENCES "Conversation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "ConversationParticipant" ADD CONSTRAINT "ConversationParticipant_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Message" ADD CONSTRAINT "Message_conversationId_fkey" FOREIGN KEY ("conversationId") REFERENCES "Conversation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Message" ADD CONSTRAINT "Message_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "MessageReport" ADD CONSTRAINT "MessageReport_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "MessageReport" ADD CONSTRAINT "MessageReport_reporterId_fkey" FOREIGN KEY ("reporterId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Favorite" ADD CONSTRAINT "Favorite_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
--- AddForeignKey
-ALTER TABLE "Favorite" ADD CONSTRAINT "Favorite_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "Business"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/admin/prisma/migrations/20260503171918_add_published_at/migration.sql b/admin/prisma/migrations/20260503171918_add_published_at/migration.sql
deleted file mode 100644
index 5c2a930..0000000
--- a/admin/prisma/migrations/20260503171918_add_published_at/migration.sql
+++ /dev/null
@@ -1,8 +0,0 @@
--- AlterTable
-ALTER TABLE "BlogPost" ADD COLUMN "publishedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
-
--- AlterTable
-ALTER TABLE "Event" ADD COLUMN "publishedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
-
--- AlterTable
-ALTER TABLE "Interview" ADD COLUMN "publishedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
diff --git a/admin/prisma/migrations/20260503172958_add_content_status/migration.sql b/admin/prisma/migrations/20260503172958_add_content_status/migration.sql
deleted file mode 100644
index f70ae9d..0000000
--- a/admin/prisma/migrations/20260503172958_add_content_status/migration.sql
+++ /dev/null
@@ -1,11 +0,0 @@
--- CreateEnum
-CREATE TYPE "ContentStatus" AS ENUM ('DRAFT', 'PUBLISHED', 'ARCHIVED');
-
--- AlterTable
-ALTER TABLE "BlogPost" ADD COLUMN "status" "ContentStatus" NOT NULL DEFAULT 'PUBLISHED';
-
--- AlterTable
-ALTER TABLE "Event" ADD COLUMN "status" "ContentStatus" NOT NULL DEFAULT 'PUBLISHED';
-
--- AlterTable
-ALTER TABLE "Interview" ADD COLUMN "status" "ContentStatus" NOT NULL DEFAULT 'PUBLISHED';
diff --git a/admin/prisma/migrations/migration_lock.toml b/admin/prisma/migrations/migration_lock.toml
deleted file mode 100644
index 044d57c..0000000
--- a/admin/prisma/migrations/migration_lock.toml
+++ /dev/null
@@ -1,3 +0,0 @@
-# Please do not edit this file manually
-# It should be added in your version-control system (e.g., Git)
-provider = "postgresql"
diff --git a/admin/prisma/schema.prisma b/admin/prisma/schema.prisma
deleted file mode 100644
index 37a4205..0000000
--- a/admin/prisma/schema.prisma
+++ /dev/null
@@ -1,426 +0,0 @@
-generator client {
- provider = "prisma-client-js"
- binaryTargets = ["native", "linux-musl", "linux-musl-openssl-3.0.x"]
-}
-
-datasource db {
- provider = "postgresql"
- url = env("DATABASE_URL")
-}
-
-model User {
- id String @id @default(uuid())
- name String
- email String @unique
- password String
- role UserRole @default(VISITOR)
- avatar String?
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- bio String?
- location 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[]
- favorites Favorite[]
- sentMessages Message[]
- reports MessageReport[]
- ratings Rating[]
- country Country? @relation(fields: [countryId], references: [id])
-}
-
-model Business {
- id String @id @default(uuid())
- name String
- category String
- location String
- description String
- logoUrl String
- videoUrl String?
- contactEmail String
- contactPhone String?
- socialLinks Json?
- verified Boolean @default(false)
- viewCount Int @default(0)
- rating Float @default(0.0)
- ratingCount Int @default(0)
- tags String[]
- isFeatured Boolean @default(false)
- founderName String?
- founderImageUrl String?
- keyMetric String?
- ownerId String @unique
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- slug String? @unique
- isActive Boolean @default(false)
- showEmail Boolean @default(true)
- showPhone Boolean @default(true)
- showSocials Boolean @default(true)
- websiteUrl String?
- 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?
- metaDescription String?
- metaTitle 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[]
- favorites Favorite[]
- homeSlides HomeSlide[]
- offers Offer[]
- ratings Rating[]
-}
-
-model BusinessCategory {
- id String @id @default(uuid())
- name String @unique
- slug String @unique
- icon String?
- isActive Boolean @default(true)
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- businesses Business[]
-}
-
-model Country {
- id String @id @default(uuid())
- name String @unique
- code String @unique
- flag String?
- isActive Boolean @default(true)
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- description String?
- businesses Business[]
- users User[]
-}
-
-model PricingPlan {
- id String @id @default(uuid())
- tier Plan @unique
- name String
- priceXOF String
- priceEUR 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 {
- id String @id @default(uuid())
- title String
- type OfferType
- price Float
- currency String @default("XOF")
- description String?
- imageUrl String
- active Boolean @default(true)
- businessId String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
-}
-
-model BlogPost {
- id String @id @default(uuid())
- title String
- excerpt String
- content String
- author String
- date DateTime @default(now())
- imageUrl String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- metaDescription String?
- metaTitle String?
- slug String? @unique
- tags String[] @default([])
- publishedAt DateTime @default(now())
- status ContentStatus @default(PUBLISHED)
- coverPosition String? @default("50% 50%")
- coverZoom Float? @default(1.0)
-}
-
-model HomeSlide {
- id String @id @default(uuid())
- type HomeSlideType @default(CUSTOM)
- businessId String?
- title String?
- subtitle String?
- imageUrl String?
- linkUrl String?
- order Int @default(0)
- isActive Boolean @default(true)
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- coverPosition String? @default("50% 50%")
- coverZoom Float? @default(1.0)
- business Business? @relation(fields: [businessId], references: [id])
-}
-
-model Interview {
- id String @id @default(uuid())
- title String
- guestName String
- companyName String
- role String
- type InterviewType
- thumbnailUrl String
- videoUrl String?
- content String?
- excerpt String
- date DateTime @default(now())
- duration String?
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- metaDescription String?
- metaTitle String?
- slug String? @unique
- tags String[] @default([])
- publishedAt DateTime @default(now())
- status ContentStatus @default(PUBLISHED)
- coverPosition String? @default("50% 50%")
- coverZoom Float? @default(1.0)
-}
-
-model Comment {
- id String @id @default(uuid())
- content String
- authorId String
- businessId String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
- business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
-}
-
-model AnalyticsEvent {
- id String @id @default(uuid())
- type String
- path String
- label String?
- value Float?
- metadata Json?
- createdAt DateTime @default(now())
- browser String?
- city String?
- country String?
- device String?
- ip String?
- os String?
- referrer String?
- userId String?
-}
-
-model Rating {
- id String @id @default(uuid())
- value Int
- userId String
- businessId String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- 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])
-}
-
-model Conversation {
- id String @id @default(uuid())
- businessId String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
- participants ConversationParticipant[]
- messages Message[]
-}
-
-model ConversationParticipant {
- id String @id @default(uuid())
- userId String
- conversationId String
- isArchived Boolean @default(false)
- conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
-
- @@unique([userId, conversationId])
-}
-
-model Message {
- id String @id @default(uuid())
- content String
- senderId String
- conversationId String
- createdAt DateTime @default(now())
- read Boolean @default(false)
- conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
- sender User @relation(fields: [senderId], references: [id], onDelete: Cascade)
- reports MessageReport[]
-}
-
-model MessageReport {
- id String @id @default(uuid())
- reason String?
- messageId String
- reporterId String
- status ReportStatus @default(PENDING)
- createdAt DateTime @default(now())
- message Message @relation(fields: [messageId], 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("{siteName}
Bonjour {name},
Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :
Ce lien expirera dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.
© 2025 {siteName}. Tous droits réservés.
")
- verifyEmailSubject String @default("Vérification de votre compte - Afrohub")
- verifyEmailTemplate String @default("{siteName}
Bonjour {name},
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 :
Si vous n'avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.
© 2025 {siteName}. Tous droits réservés.
")
-}
-
-model OneShotPlan {
- id String @id @default(uuid())
- type OneShotType @unique
- name String
- priceXOF Int @default(0)
- priceEUR Int @default(0)
- description String?
- updatedAt DateTime @updatedAt
-}
-
-enum OneShotType {
- BUMP
- POST_EVENT
- POST_NEWS
- AD_DIRECTORY
-}
-
-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([])
- publishedAt DateTime @default(now())
- status ContentStatus @default(PUBLISHED)
- coverPosition String? @default("50% 50%")
- coverZoom Float? @default(1.0)
-}
-
-model Favorite {
- id String @id @default(uuid())
- userId String
- businessId String
- createdAt DateTime @default(now())
- business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
-
- @@unique([userId, businessId])
-}
-
-enum HomeSlideType {
- BUSINESS
- CUSTOM
-}
-
-enum ContentStatus {
- DRAFT
- PENDING
- PUBLISHED
- ARCHIVED
-}
-
-enum RatingStatus {
- PENDING
- APPROVED
- REJECTED
-}
-
-enum ReportStatus {
- PENDING
- RESOLVED
- DISMISSED
-}
-
-enum UserRole {
- VISITOR
- ENTREPRENEUR
- ADMIN
-}
-
-enum Plan {
- STARTER
- BOOSTER
- EMPIRE
-}
-
-enum OfferType {
- PRODUCT
- SERVICE
-}
-
-enum InterviewType {
- VIDEO
- ARTICLE
-}
diff --git a/package.json b/package.json
index 54f4bd8..c73323d 100644
--- a/package.json
+++ b/package.json
@@ -11,8 +11,8 @@
"dev:admin": "npm run dev --prefix admin -- -p 3001",
"all": "concurrently \"npm run dev\" \"npm run dev:admin\"",
"build": "prisma generate && next build && npm run build:admin",
- "build:admin": "npm install --prefix admin --legacy-peer-deps && prisma generate && npm run build --prefix admin",
- "generate": "npx prisma generate && cd admin && npx prisma generate && cd ..",
+ "build:admin": "npm install --prefix admin --legacy-peer-deps && npm run build --prefix admin",
+ "generate": "npx prisma generate && cd admin && npx prisma generate --schema=../prisma/schema.prisma && cd ..",
"start": "npx prisma migrate deploy && next start",
"start:admin": "npm run start --prefix admin",
"db:migrate": "prisma migrate dev",