admin build v3

This commit is contained in:
2026-05-11 17:57:54 +02:00
parent cfc5f1ac02
commit 2cab2ddd1d
8 changed files with 5201 additions and 7636 deletions

View File

@@ -9,13 +9,6 @@ const nextConfig: NextConfig = {
ignoreBuildErrors: true, ignoreBuildErrors: true,
}, },
// 2. On simplifie Turbopack.
// Faire pointer le root sur ".." est risqué en production sur Dokploy.
// Next.js trouvera les modules parents tout seul grâce au hoisting de NPM.
turbopack: {
root: path.join(__dirname, ".."),
},
// 3. (Optionnel) Pour faciliter le chargement des images si tu en as // 3. (Optionnel) Pour faciliter le chargement des images si tu en as
images: { images: {
remotePatterns: [ remotePatterns: [

7558
admin/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,11 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
export const dynamic = 'force-dynamic'; export const dynamic = 'force-dynamic';
import { Inter } from "next/font/google";
import "./globals.css"; import "./globals.css";
import Sidebar from "@/components/Sidebar";
import { Toaster } from 'react-hot-toast';
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "AfroAdmin - Administration Afrohub", title: "AfroAdmin - Administration Afrohub",
@@ -15,9 +19,11 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="fr"> <html lang="fr">
<body> <body className={inter.className}>
<div className="flex min-h-screen"> <div className="flex min-h-screen">
<Sidebar />
<main className="admin-content flex-1"> <main className="admin-content flex-1">
<Toaster position="top-right" />
{children} {children}
</main> </main>
</div> </div>

View File

@@ -1,3 +1,4 @@
"use client";
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
@@ -5,14 +6,18 @@ import { LayoutDashboard, ArrowLeft } from 'lucide-react';
export default function NotFound() { export default function NotFound() {
return ( return (
<div className="min-h-screen bg-slate-950 flex items-center justify-center p-6"> <div className="min-h-screen bg-slate-950 flex items-center justify-center p-4">
<div className="max-w-md w-full text-center"> <div className="max-w-md w-full text-center space-y-8">
<div className="mb-8"> <div className="relative">
<div className="inline-flex items-center justify-center w-20 h-20 rounded-2xl bg-indigo-500/10 border border-indigo-500/20 mb-6"> <h1 className="text-[150px] font-black text-slate-900 leading-none select-none">404</h1>
<span className="text-4xl font-bold text-indigo-400">404</span> <div className="absolute inset-0 flex items-center justify-center">
<span className="text-4xl font-bold text-white tracking-widest uppercase">Perdu ?</span>
</div> </div>
<h1 className="text-3xl font-bold text-white mb-2">Page d'administration introuvable</h1> </div>
<p className="text-slate-400">La ressource que vous recherchez n'existe pas ou a é déplacée.</p>
<div className="space-y-2">
<h2 className="text-2xl font-bold text-white">Cette page n'existe pas</h2>
<p className="text-slate-400">Le contenu que vous recherchez semble avoir é déplacé ou supprimé.</p>
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
@@ -23,13 +28,13 @@ export default function NotFound() {
<LayoutDashboard className="w-5 h-5" /> <LayoutDashboard className="w-5 h-5" />
Retour au Dashboard Retour au Dashboard
</Link> </Link>
<Link <button
href="/dashboard" onClick={() => window.history.back()}
className="w-full flex items-center justify-center gap-2 px-6 py-3 bg-slate-900 text-slate-300 border border-slate-800 rounded-xl font-semibold hover:bg-slate-800 transition-colors" className="w-full flex items-center justify-center gap-2 px-6 py-3 bg-slate-900 text-slate-300 border border-slate-800 rounded-xl font-semibold hover:bg-slate-800 transition-colors"
> >
<ArrowLeft className="w-5 h-5" /> <ArrowLeft className="w-5 h-5" />
Page précédente Page précédente
</Link> </button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,4 +1,5 @@
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
export const dynamic = 'force-dynamic';
export default function Home() { export default function Home() {
redirect("/dashboard"); redirect("/dashboard");

View File

@@ -2,16 +2,13 @@ import { PrismaClient } from '@prisma/client'
import { PrismaPg } from '@prisma/adapter-pg' import { PrismaPg } from '@prisma/adapter-pg'
import pg from 'pg' import pg from 'pg'
const globalForPrisma = globalThis as unknown as { prisma_v4: PrismaClient } const globalForPrisma = globalThis as unknown as { prisma_v4?: PrismaClient }
function makePrisma() { function createPrismaClient() {
const connectionString = process.env.DATABASE_URL const connectionString = process.env.DATABASE_URL
if (!connectionString && process.env.NODE_ENV === 'production') { if (!connectionString && process.env.NODE_ENV === 'production') {
// If we're in production build and DATABASE_URL is missing, console.warn("DATABASE_URL is missing during build.");
// we return a proxy or a dummy to avoid crashing the build worker
// if it just evaluates the module.
console.warn("DATABASE_URL is missing. Prisma Client might fail if called.");
} }
const pool = new pg.Pool({ connectionString: connectionString || "" }) const pool = new pg.Pool({ connectionString: connectionString || "" })
@@ -19,8 +16,13 @@ function makePrisma() {
return new PrismaClient({ adapter }) return new PrismaClient({ adapter })
} }
export const prisma = globalForPrisma.prisma_v4 || makePrisma() export const prisma = new Proxy({} as PrismaClient, {
get(target, prop) {
if (!globalForPrisma.prisma_v4) {
globalForPrisma.prisma_v4 = createPrismaClient();
}
return (globalForPrisma.prisma_v4 as any)[prop];
}
});
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma_v4 = prisma export default prisma;
export default prisma

5206
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,12 +6,15 @@
"engines": { "engines": {
"node": "24.x" "node": "24.x"
}, },
"workspaces": [
"admin"
],
"scripts": { "scripts": {
"dev": "next dev -p 3000", "dev": "next dev -p 3000",
"dev:admin": "npm run dev --prefix admin -- -p 3001", "dev:admin": "npm run dev --prefix admin -- -p 3001",
"all": "concurrently \"npm run dev\" \"npm run dev:admin\"", "all": "concurrently \"npm run dev\" \"npm run dev:admin\"",
"build": "prisma generate && next build", "build": "prisma generate && next build",
"build:admin": "npm install --prefix admin --legacy-peer-deps && cd admin && npx prisma generate --schema=../prisma/schema.prisma && next build --webpack", "build:admin": "cd admin && npx prisma generate --schema=../prisma/schema.prisma && next build",
"generate": "npx prisma generate && cd admin && npx prisma generate --schema=../prisma/schema.prisma && cd ..", "generate": "npx prisma generate && cd admin && npx prisma generate --schema=../prisma/schema.prisma && cd ..",
"start": "npx prisma migrate deploy && next start", "start": "npx prisma migrate deploy && next start",
"start:admin": "npm run start --prefix admin", "start:admin": "npm run start --prefix admin",
@@ -37,7 +40,7 @@
"dotenv": "^17.3.1", "dotenv": "^17.3.1",
"jiti": "^2.6.1", "jiti": "^2.6.1",
"lucide-react": "^0.554.0", "lucide-react": "^0.554.0",
"next": "^16.1.6", "next": "16.2.3",
"nodemailer": "^8.0.6", "nodemailer": "^8.0.6",
"pg": "^8.19.0", "pg": "^8.19.0",
"postcss": "^8.5.10", "postcss": "^8.5.10",
@@ -45,6 +48,7 @@
"react": "^19.2.0", "react": "^19.2.0",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",
"react-hot-toast": "^2.6.0", "react-hot-toast": "^2.6.0",
"react-is": "^19.2.6",
"recharts": "^3.8.1", "recharts": "^3.8.1",
"sanitize-html": "^2.17.3", "sanitize-html": "^2.17.3",
"tailwindcss": "^4.2.2", "tailwindcss": "^4.2.2",
@@ -62,4 +66,4 @@
"postcss": "^8.5.10", "postcss": "^8.5.10",
"@hono/node-server": "^1.19.13" "@hono/node-server": "^1.19.13"
} }
} }