derniere
@ -1,16 +1,16 @@
|
||||
"use client"; // ✅ Indique que ce composant fonctionne côté client
|
||||
"use client";
|
||||
|
||||
import { useParams } from "next/navigation"; // ✅ Nouvelle méthode pour récupérer `params`
|
||||
import { useParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import ContentSectionCompetencesContainer from "../../components/ContentSectionCompetencesContainer";
|
||||
|
||||
export default function CompetencePage() {
|
||||
const params = useParams(); // ✅ Récupérer `params` correctement
|
||||
const params = useParams();
|
||||
const [slug, setSlug] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (params?.slug) {
|
||||
setSlug(params.slug as string); // ✅ Assurer que `slug` est bien une string
|
||||
setSlug(params.slug as string);
|
||||
}
|
||||
}, [params]);
|
||||
|
||||
|
||||
@ -2,16 +2,15 @@
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { getApiUrl } from "../utils/getApiUrl"; // 🔥 Import de l'URL dynamique
|
||||
import CarouselCompetences from "../components/CarouselCompetences"; // 🔥 Import du composant CarouselCompetences
|
||||
import { getApiUrl } from "../utils/getApiUrl";
|
||||
import CarouselCompetences from "../components/CarouselCompetences";
|
||||
|
||||
export default function Page() {
|
||||
const [competences, setCompetences] = useState([]); // 🔥 Stocker les compétences une seule fois
|
||||
const apiUrl = getApiUrl(); // 🔥 Définition de l'URL API
|
||||
const [competences, setCompetences] = useState([]);
|
||||
const apiUrl = getApiUrl();
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchCompetences() {
|
||||
console.log("🔍 API utilisée pour les compétences :", apiUrl);
|
||||
try {
|
||||
const response = await fetch(`${apiUrl}/api/competences?populate=*`);
|
||||
if (!response.ok) {
|
||||
@ -24,13 +23,13 @@ export default function Page() {
|
||||
}
|
||||
}
|
||||
|
||||
fetchCompetences(); // 🔥 Exécuter une seule fois au montage du composant
|
||||
}, [apiUrl]); // ✅ Exécuter `useEffect()` uniquement si `apiUrl` change
|
||||
fetchCompetences();
|
||||
}, [apiUrl]);
|
||||
|
||||
return (
|
||||
<main className="w-full p-3 mt-5 mb-5">
|
||||
|
||||
{/* Affichage d'un message si aucune compétence n'est trouvée */}
|
||||
|
||||
{competences.length === 0 ? (
|
||||
<p className="text-center text-gray-500">Aucune compétence disponible.</p>
|
||||
) : (
|
||||
@ -47,7 +46,6 @@ export default function Page() {
|
||||
key={competence.id}
|
||||
className="bg-white/70 rounded-lg shadow-md overflow-hidden w-full h-auto flex flex-col transform transition-all duration-300 hover:scale-105 hover:shadow-xl p-4"
|
||||
>
|
||||
{/* Lien vers la page de détail de la compétence */}
|
||||
<Link href={`/competences/${competence.slug}`}>
|
||||
<div className="overflow-hidden w-full h-64 mb-4">
|
||||
<CarouselCompetences images={images} className="w-full h-full object-cover" />
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { getApiUrl } from "../../utils/getApiUrl"; // 🔥 Import de l'URL dynamique
|
||||
// // Composant principal de la page des messages
|
||||
import { getApiUrl } from "../../utils/getApiUrl";
|
||||
export default async function MessagesPage() {
|
||||
// Récupération des messages depuis l'API Strapi
|
||||
const apiUrl = getApiUrl();
|
||||
const res = await fetch(`${apiUrl}/api/messages`);
|
||||
const { data } = await res.json();
|
||||
@ -11,19 +9,14 @@ export default async function MessagesPage() {
|
||||
{/* Titre de la page */}
|
||||
<h1 className="text-3xl font-bold text-center mb-6">📬 Messages reçus</h1>
|
||||
|
||||
{/* Affichage d'un message si aucun message n'est reçu */}
|
||||
{data.length === 0 ? (
|
||||
<p className="text-center text-gray-600">Aucun message reçu.</p>
|
||||
) : (
|
||||
<ul className="space-y-4">
|
||||
{/* Boucle sur les messages pour les afficher */}
|
||||
{data.map((msg: any) => (
|
||||
<li key={msg.id} className="p-4 border rounded shadow">
|
||||
{/* Affichage du nom et de l'email de l'expéditeur */}
|
||||
<p><strong>👤 {msg.name}</strong> ({msg.email})</p>
|
||||
{/* Affichage de la date de réception du message */}
|
||||
<p>📅 {new Date(msg.createdAt).toLocaleString("fr-FR")}</p>
|
||||
{/* Affichage du contenu du message */}
|
||||
<p className="mt-2">{msg.message}</p>
|
||||
</li>
|
||||
))}
|
||||
|
||||
|
After Width: | Height: | Size: 528 KiB |
|
After Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 330 KiB |
|
After Width: | Height: | Size: 780 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 561 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 482 KiB |
|
After Width: | Height: | Size: 539 KiB |
|
After Width: | Height: | Size: 315 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 642 KiB |
|
After Width: | Height: | Size: 607 KiB |
|
After Width: | Height: | Size: 489 KiB |
|
After Width: | Height: | Size: 478 KiB |
|
After Width: | Height: | Size: 589 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 824 KiB |
|
After Width: | Height: | Size: 379 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 430 KiB |
|
After Width: | Height: | Size: 428 KiB |
|
After Width: | Height: | Size: 301 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 463 KiB |
|
After Width: | Height: | Size: 918 KiB |
|
After Width: | Height: | Size: 779 KiB |
|
After Width: | Height: | Size: 550 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 603 KiB |
|
After Width: | Height: | Size: 388 KiB |
|
After Width: | Height: | Size: 857 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 438 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 838 KiB |
|
After Width: | Height: | Size: 808 KiB |
|
After Width: | Height: | Size: 867 KiB |
|
After Width: | Height: | Size: 409 KiB |
|
After Width: | Height: | Size: 437 KiB |
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 817 KiB |
|
After Width: | Height: | Size: 925 KiB |
|
After Width: | Height: | Size: 654 KiB |
|
After Width: | Height: | Size: 596 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 517 KiB |
|
After Width: | Height: | Size: 550 KiB |
|
After Width: | Height: | Size: 654 KiB |
|
After Width: | Height: | Size: 327 KiB |
|
After Width: | Height: | Size: 205 KiB |
|
After Width: | Height: | Size: 475 KiB |
|
After Width: | Height: | Size: 524 KiB |
|
After Width: | Height: | Size: 569 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 445 KiB |
|
After Width: | Height: | Size: 980 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 316 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
After Width: | Height: | Size: 530 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 472 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 360 KiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 326 KiB |
BIN
app/assets/images/impressions/agencement2_resultat.webp
Normal file
|
After Width: | Height: | Size: 509 KiB |
BIN
app/assets/images/impressions/agencement3_resultat.webp
Normal file
|
After Width: | Height: | Size: 1016 KiB |
BIN
app/assets/images/impressions/agencement_resultat.webp
Normal file
|
After Width: | Height: | Size: 361 KiB |
BIN
app/assets/images/impressions/casque2_resultat.webp
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
app/assets/images/impressions/casque3_resultat.webp
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
app/assets/images/impressions/casque4_resultat.webp
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
app/assets/images/impressions/casque5_resultat.webp
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
app/assets/images/impressions/cybersabre_resultat.webp
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
app/assets/images/impressions/gravure_resultat.webp
Normal file
|
After Width: | Height: | Size: 449 KiB |
BIN
app/assets/images/impressions/gravurevegeta_resultat.webp
Normal file
|
After Width: | Height: | Size: 82 KiB |