diff --git a/admin/src/app/actions/settings.ts b/admin/src/app/actions/settings.ts index 3ade872..9fe18b0 100644 --- a/admin/src/app/actions/settings.ts +++ b/admin/src/app/actions/settings.ts @@ -29,6 +29,7 @@ export async function getSiteSettings() { homeBlogIds: [], homeBlogCategories: [], homeCategories: ["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"], + notFoundQuotes: ["L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse."], resetPasswordSubject: "Réinitialisation de votre mot de passe - Afrohub", resetPasswordTemplate: `

{siteName}

diff --git a/admin/src/app/settings/page.tsx b/admin/src/app/settings/page.tsx index 7b0be2c..e60498d 100644 --- a/admin/src/app/settings/page.tsx +++ b/admin/src/app/settings/page.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useState, useEffect, useTransition } from 'react'; -import { Save, Globe, Mail, Phone, MapPin, Share2, Link as LinkIcon, Loader2, Newspaper, Briefcase } from 'lucide-react'; +import { Save, Globe, Mail, Phone, MapPin, Share2, Link as LinkIcon, Loader2, Newspaper, Briefcase, Plus, Trash2 } from 'lucide-react'; import { getSiteSettings, updateSiteSettings } from '@/app/actions/settings'; import { toast } from 'react-hot-toast'; import { getBlogPosts } from '@/app/actions/actualites'; @@ -46,6 +46,7 @@ export default function SettingsPage({ const [selectedPostIds, setSelectedPostIds] = useState([]); const [selectedHomeCategories, setSelectedHomeCategories] = useState([]); const [selectedBlogCategories, setSelectedBlogCategories] = useState([]); + const [notFoundQuotes, setNotFoundQuotes] = useState([]); const [resetPasswordTemplate, setResetPasswordTemplate] = useState(''); const [verifyEmailTemplate, setVerifyEmailTemplate] = useState(''); @@ -65,6 +66,7 @@ export default function SettingsPage({ setSelectedPostIds(settingsData?.homeBlogIds || []); setSelectedHomeCategories(settingsData?.homeCategories || []); setSelectedBlogCategories(settingsData?.homeBlogCategories || []); + setNotFoundQuotes(settingsData?.notFoundQuotes || ["L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse."]); setResetPasswordTemplate(settingsData?.resetPasswordTemplate || ''); setVerifyEmailTemplate(settingsData?.verifyEmailTemplate || ''); } catch (error) { @@ -99,6 +101,7 @@ export default function SettingsPage({ homeBlogIds: selectedPostIds, homeBlogCategories: selectedBlogCategories, homeCategories: selectedHomeCategories, + notFoundQuotes: notFoundQuotes.filter(q => q.trim() !== ''), resetPasswordSubject: formData.get('resetPasswordSubject'), resetPasswordTemplate: resetPasswordTemplate, verifyEmailSubject: formData.get('verifyEmailSubject'), @@ -133,6 +136,22 @@ export default function SettingsPage({ ); }; + const handleAddQuote = () => { + setNotFoundQuotes(prev => [...prev, '']); + }; + + const handleUpdateQuote = (index: number, value: string) => { + setNotFoundQuotes(prev => { + const updated = [...prev]; + updated[index] = value; + return updated; + }); + }; + + const handleRemoveQuote = (index: number) => { + setNotFoundQuotes(prev => prev.filter((_, i) => i !== index)); + }; + if (loading) { return (
@@ -205,6 +224,57 @@ export default function SettingsPage({
+ {/* Section Page 404 - Phrases */} +
+
+
+ +

Phrases de la Page 404

+
+ + {notFoundQuotes.length} configurée{notFoundQuotes.length > 1 ? 's' : ''} + +
+
+

+ Configurez ici les différentes phrases ou citations qui s'afficheront de manière aléatoire sur la page d'erreur 404. +

+ +
+ {notFoundQuotes.map((quote, index) => ( +
+ handleUpdateQuote(index, e.target.value)} + placeholder="Saisissez une citation..." + className="flex-grow bg-slate-950 border border-slate-700 rounded-xl p-3 text-white focus:outline-none focus:border-indigo-500 text-sm" + /> + {notFoundQuotes.length > 1 && ( + + )} +
+ ))} +
+ + +
+
+ {/* Section Page d'Accueil - Secteurs */}
diff --git a/app/not-found.tsx b/app/not-found.tsx index 95c57bd..414f118 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -1,8 +1,17 @@ import React from 'react'; import Link from 'next/link'; -import { Home, ArrowLeft, Search } from 'lucide-react'; +import { Home, Search } from 'lucide-react'; +import { getSiteSettings } from '../lib/settings'; + +export default async function NotFound() { + const settings = await getSiteSettings(); + const quotes = (settings as any)?.notFoundQuotes && (settings as any).notFoundQuotes.length > 0 + ? (settings as any).notFoundQuotes + : ["L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse."]; + + // Sélection d'une phrase aléatoire + const randomQuote = quotes[Math.floor(Math.random() * quotes.length)]; -export default function NotFound() { return (
@@ -41,10 +50,11 @@ export default function NotFound() {

- "L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse." + "{randomQuote}"

); } + diff --git a/lib/settings.ts b/lib/settings.ts index 696c4f2..25f771e 100644 --- a/lib/settings.ts +++ b/lib/settings.ts @@ -19,7 +19,8 @@ export async function getSiteSettings() { homeBlogSelection: "latest", homeBlogIds: [], homeBlogCategories: [], - homeCategories: ["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"] + homeCategories: ["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"], + notFoundQuotes: ["L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse."] }; try { diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e904e97..e89673a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -332,6 +332,7 @@ model SiteSetting { deleteAccountTemplate String @default("

{siteName}

Bonjour {name},

Votre demande de suppression de compte a bien été prise en compte. Votre compte sera définitivement supprimé le {deletionDate}.

Si vous changez d'avis, vous pouvez réactiver votre compte avant cette date en cliquant sur le bouton ci-dessous :

Passé ce délai, toutes vos données seront définitivement effacées.


© 2025 {siteName}. Tous droits réservés.

") reactivateAccountSubject String @default("Réactivation de votre compte - Afrohub") reactivateAccountTemplate String @default("

{siteName}

Bonjour {name},

Nous avons bien reçu votre demande de réactivation de compte.

Raison invoquée :
{reason}

Votre compte est désormais actif. Vous pouvez vous connecter à nouveau.


© 2025 {siteName}. Tous droits réservés.

") + notFoundQuotes String[] @default(["L'échec est une étape vers la réussite, mais une erreur 404 est juste une impasse."]) } model OneShotPlan {