diff --git a/frontend/index.html b/frontend/index.html index 5c3bad9..7c699a9 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,6 +5,18 @@ bureau d’études Maîtrise d’oeuvre + + + + + + + + + + + + diff --git a/frontend/src/api.js b/frontend/src/api.js index 1d2303d..6cd5f37 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -1,8 +1,12 @@ import axios from 'axios'; +// Création de l'instance Axios const api = axios.create({ baseURL: 'https://preprod.octopusdesign.fr/api-octopus/server/wp-json', withCredentials: true, }); -export default api; \ No newline at end of file + + +// Exportation de l'instance Axios par défaut +export default api; diff --git a/frontend/src/components/Pages/Home.jsx b/frontend/src/components/Pages/Home.jsx index 7b3065c..ad78ba5 100644 --- a/frontend/src/components/Pages/Home.jsx +++ b/frontend/src/components/Pages/Home.jsx @@ -5,107 +5,33 @@ import api from "../../api"; import ModernSpinner from "../SpinnerModerne"; import Expertises from "../Expertises"; import ConstructSection from "../ConstructSection"; -import { - Box, - Grid, - Typography, - Button, - Card, - CardContent, -} from "@mui/material"; +import { Box, Grid, Typography, Button, Card, CardContent } from "@mui/material"; import Logo from "../../assets/logo-in3-mobil.svg"; const Home = () => { - const [backgroundImage, setBackgroundImage] = useState(null); - const [useGradient, setUseGradient] = useState(false); - const [heroTitle, setHeroTitle] = useState("Titre par défaut"); - const [heroTitleColor, setHeroTitleColor] = useState("#ffffff"); - const [heroText, setHeroText] = useState("Texte par défaut"); - const [heroTextColor, setHeroTextColor] = useState("#ffffff"); - const [metaTitle, setMetaTitle] = useState("Titre par défaut"); - const [metaDescription, setMetaDescription] = useState( - "Description par défaut." - ); - - //optionally - const [canonicalUrl, setCanonicalUrl] = useState(null); + const [pageData, setPageData] = useState(null); + const [heroImage, setHeroImage] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); - //Construction - const [constructTitle, setConstructTitle] = useState("Construisons vos projets"); - const [constructSubtitle, setConstructSubtitle] = useState("ensemble"); - const [constructSector, setConstructSector] = useState("Industriel | Tertiaire | Privée"); - const [constructText, setConstructText] = useState("IN3, bureau d'études Ingénierie et Maîtrise d’œuvre, est implanté depuis 20 ans sur Le Mans. Nous étudions vos projets en structure, gros œuvre, électricité courants forts et faibles, et fluides, tout corps d'état."); - const [constructNoteText, setConstructNoteText] = useState("À votre écoute, nous travaillons avec et pour vous dans le but de satisfaire vos besoins tant sur le plan architectural que technique, méthodologique et/ou économique."); - const [missionTitle, setMissionTitle] = useState("Nos missions principales"); - const [missionItems, setMissionItems] = useState([ - { label: "Diagnostics | Sécurité", top: "20%", left: "50%" }, - { label: "Études techniques", top: "50%", left: "30%" }, - { label: "Bureau d'études | Maîtrise d’œuvre", top: "70%", left: "60%" }, - ]); - - // ACF Expertise - const [expertiseTitle, setExpertiseTitle] = useState( - "Titre Pourquoi Nous Choisir ?" - ); - const [expertise1Title, setExpertise1Title] = useState("Titre Expertise 1"); - const [expertise1Text, setExpertise1Text] = useState("Text Expertise 1"); - const [expertise2Title, setExpertise2Title] = useState("Titre Expertise 2"); - const [expertise2Text, setExpertise2Text] = useState("Text Expertise 2"); - const [expertise3Title, setExpertise3Title] = useState("Titre Expertise 3"); - const [expertise3Text, setExpertise3Text] = useState("Text Expertise 3"); - useEffect(() => { const fetchPageData = async () => { try { setIsLoading(true); setError(null); - const response = await api.get( - "wp/v2/pages/13?_fields=acf,rank_math_title,rank_math_description" - ); - const { acf, rank_math_title, rank_math_description } = response.data; + const response = await api.get("wp/v2/pages/13?_fields=acf,rank_math_title,rank_math_description"); + const pageContent = response.data; + setPageData(pageContent); - // Métadonnées SEO - setMetaTitle(rank_math_title || "Titre par défaut"); - setMetaDescription(rank_math_description || "Description par défaut."); - - // Récupération de l'URL canonique - setCanonicalUrl(acf?.canonical_url || window.location.href); - - // Données Hero - setUseGradient(acf?.enable_gradient ?? false); - setHeroTitle(acf?.hero_title || "Titre principal"); - setHeroTitleColor(acf?.hero_title_color || "#ffffff"); - setHeroText(acf?.hero_text || "Texte par défaut"); - setHeroTextColor(acf?.hero_text_color || "#ffffff"); - - // Image de fond - if (acf?.img_hero) { - const mediaResponse = await api.get(`wp/v2/media/${acf.img_hero}`); - setBackgroundImage(mediaResponse.data.source_url); + // Vérification et récupération de l'image Hero depuis l'API media de WordPress + const heroImageId = pageContent.acf?.img_hero; + if (heroImageId) { + const mediaResponse = await api.get(`wp/v2/media/${heroImageId}`); + setHeroImage(mediaResponse.data.source_url); } else { - setBackgroundImage(null); + setHeroImage(null); } - - // Section Construction - setConstructTitle(acf?.gdc_construct.construct_title || "Construisons vos projets"); - setConstructSubtitle(acf?.gdc_construct.construct_subtitle || "ensemble"); - setConstructText(acf?.gdc_construct.construct_text || "Texte par défaut"); - setConstructSector(acf?.gdc_construct.construct_sector || "Secteurs"); - setConstructNoteText(acf?.gdc_construct.construct_note || "Note société"); - setMissionTitle(acf?.mission_title || "Nos missions principales"); - setMissionItems(acf?.mission_items || []); - - // Récupération du titre de la deuxième section Expertise - setExpertiseTitle(acf?.titre_expertise || "Pourquoi Nous Choisir ?"); - setExpertise1Title(acf?.gdc_expert.titre_expertise_1 || "Expertise 1"); - setExpertise1Text(acf?.gdc_expert.text_expertise_1 || "Text Expertise 1"); - setExpertise2Title(acf?.gdc_expert.titre_expertise_2 || "Expertise 2"); - setExpertise2Text(acf?.gdc_expert.text_expertise_2 || "Text Expertise 2"); - setExpertise3Title(acf?.gdc_expert.titre_expertise_3 || "Expertise 3"); - setExpertise3Text(acf?.gdc_expert.text_expertise_3 || "Text Expertise 3"); } catch (error) { console.error("Erreur lors de la récupération des données :", error); setError("Impossible de charger les données. Veuillez réessayer."); @@ -129,106 +55,82 @@ const Home = () => { if (error) { return (
- Logo + Logo

{error}

); } + const { acf, rank_math_title, rank_math_description } = pageData || {}; + return (
{/* SEO */} - + {/* Section Héros */} {/* Section Construisons */} + {/* Section Expertises */} - {/* Section Désir : Témoignages */} + {/* Section Témoignages */} - + Ce que disent nos clients - + - "Un service exceptionnel, une équipe formidable !" + "Un service exceptionnel, une équipe formidable !" - + - Client 1 - + "Des résultats impressionnants pour notre projet." - + - Client 2 @@ -239,12 +141,7 @@ const Home = () => { {/* Section Action */} - + Prêt à Commencer ? @@ -268,4 +165,4 @@ const Home = () => { ); }; -export default Home; +export default Home; \ No newline at end of file diff --git a/frontend/src/components/Pages/Post.jsx b/frontend/src/components/Pages/Post.jsx index 1018613..a7db61f 100644 --- a/frontend/src/components/Pages/Post.jsx +++ b/frontend/src/components/Pages/Post.jsx @@ -3,6 +3,7 @@ import { Grid, Card, CardContent, CardMedia, Typography, Box } from '@mui/materi import api from '../../api'; // Adaptez le chemin vers l'instance Axios + const Post = () => { const [posts, setPosts] = useState([]); diff --git a/frontend/src/components/SEO.jsx b/frontend/src/components/SEO.jsx index 9ecd5be..34c9129 100644 --- a/frontend/src/components/SEO.jsx +++ b/frontend/src/components/SEO.jsx @@ -1,23 +1,73 @@ -import React from 'react'; -import { Helmet } from 'react-helmet-async'; +import React, { useEffect, useState } from "react"; +import { Helmet } from "react-helmet-async"; +import axios from "axios"; -const SEO = ({ title, description, canonicalUrl }) => { - return ( - - {/* Title et Description */} - {title || 'Titre par défaut'} - - {canonicalUrl && } +const SEO = ({ + postId, + defaultTitle = "Titre par défaut", + defaultDescription = "Description par défaut", + defaultCanonicalUrl = "", + defaultOgImage = "https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif" +}) => { + + const [metaData, setMetaData] = useState({ + title: defaultTitle, + description: defaultDescription, + canonicalUrl: defaultCanonicalUrl, + ogTitle: defaultTitle, + ogDescription: defaultDescription, + ogImage: defaultOgImage, + }); - {/* Preconnect */} - - + useEffect(() => { + if (!postId) return; - {/* DNS Prefetch */} - - - - ); + const fetchMetaData = async () => { + try { + const { data } = await axios.get( + `https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/pages/${postId}` + ); + + if (data && data.rank_math_og) { + setMetaData((prev) => ({ + ...prev, + title: data.rank_math_og.og_title || prev.title, + description: data.rank_math_og.og_description || prev.description, + ogTitle: data.rank_math_og.og_title || prev.title, + ogDescription: data.rank_math_og.og_description || prev.description, + ogImage: data.rank_math_og.og_image || prev.ogImage, + canonicalUrl: data.acf?.canonical_url || window.location.href + })); + } + } catch (error) { + console.error("⚠️ Erreur lors de la récupération des métadonnées SEO :", error); + } + }; + + fetchMetaData(); + }, [postId]); + + return ( + + {/* SEO standard */} + {metaData.title} + + {metaData.canonicalUrl && } + + {/* Open Graph (Facebook, LinkedIn) */} + + + + + + + {/* Twitter Cards */} + + + + + + ); }; export default SEO; \ No newline at end of file diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index c2a0ad0..f2c8af7 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,36 +1,46 @@ -import React,{ lazy, Suspense } from "react"; +import React, { lazy, Suspense } from "react"; import ReactDOM from "react-dom/client"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { ThemeProvider } from "@mui/material/styles"; import theme from "./theme"; import { HelmetProvider } from "react-helmet-async"; -import SimpleReactLightbox from "simple-react-lightbox"; - +import SimpleReactLightbox from "simple-react-lightbox"; // Lazy loading des pages const Home = lazy(() => import('./components/pages/Home.jsx')); const About = lazy(() => import('./components/Pages/About')); const Contact = lazy(() => import('./components/Pages/Contact')); - -// import Home from "./components/Pages/Home.jsx"; -import Post from "./components/Pages/Post"; -// import About from "./components/Pages/About"; -// import Contact from "./components/Pages/Contact"; -import Search from "./components/Pages/Search"; // Nouveau composant pour la recherche -import Header from "./components/Header"; -import Footer from './components/Footer'; - +const Post = lazy(() => import('./components/Pages/Post')); +const Search = lazy(() => import('./components/Pages/Search')); // Nouveau composant pour la recherche // Import des services import ServiceUn from "./components/Pages/ServiceUn.jsx"; import ServiceDeux from "./components/Pages/ServiceDeux.jsx"; import ServiceTrois from "./components/Pages/ServiceTrois.jsx"; -function App() { +// Import des composants globaux +import Header from "./components/Header"; +import Footer from './components/Footer'; + +function YourApp() { return ( - - - + Chargement...
}> + +
+ + } /> + } /> + } /> + } /> + } /> {/* Route pour les recherches */} + {/* Routes pour les services */} + } /> + } /> + } /> + +