diff --git a/.DS_Store b/.DS_Store index 649816c..fb157a7 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/frontend/src/components/ConstructSection.jsx b/frontend/src/components/ConstructSection.jsx index 90a6341..f1f48ee 100644 --- a/frontend/src/components/ConstructSection.jsx +++ b/frontend/src/components/ConstructSection.jsx @@ -1,12 +1,16 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import { Box, Typography, - Button, Grid, Card, CardContent, + Accordion, + AccordionSummary, + AccordionDetails, } from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import api from "../api"; const ConstructSection = ({ constructTitle, @@ -17,85 +21,96 @@ const ConstructSection = ({ missionTitle, missionItems, }) => { + // État pour gérer l'ouverture des accordéons + const [expanded, setExpanded] = useState(false); + const [missions, setMissions] = useState([]); + + // ✅ Chargement initial des missions depuis localStorage ou WordPress + useEffect(() => { + const loadMissions = async () => { + try { + // 1️⃣ Vérifier si localStorage contient des missions + const storedMissions = JSON.parse(localStorage.getItem("missions")); + + if (storedMissions && storedMissions.length > 0) { + setMissions(storedMissions); + console.log("✅ Missions chargées depuis localStorage !"); + } else { + // 2️⃣ Si localStorage est vide, récupérer les missions depuis WordPress + const response = await api.get("wp/v2/pages/13?_fields=acf"); + + if (response.data.acf?.mission && Array.isArray(response.data.acf.mission)) { + setMissions(response.data.acf.mission); + localStorage.setItem("missions", JSON.stringify(response.data.acf.mission)); // Sauvegarde en local + console.log("✅ Missions chargées depuis WordPress !"); + } else { + // 3️⃣ Si aucune mission dans WordPress, utiliser des valeurs par défaut + const defaultMissions = [ + { title: "📌 Mission 1", details: "Détails de la mission 1" }, + { title: "📌 Mission 2", details: "Détails de la mission 2" }, + { title: "📌 Mission 3", details: "Détails de la mission 3" }, + ]; + setMissions(defaultMissions); + localStorage.setItem("missions", JSON.stringify(defaultMissions)); + console.log("⚠️ Aucune mission trouvée, valeurs par défaut utilisées !"); + } + } + } catch (error) { + console.error("❌ Erreur lors du chargement des missions :", error); + } + }; + + loadMissions(); + }, []); + + // ✅ Mise à jour automatique de localStorage quand missions change + useEffect(() => { + if (missions.length > 0) { + localStorage.setItem("missions", JSON.stringify(missions)); + } + }, [missions]); + + // ✅ Gestion des changements depuis d'autres onglets/navigateurs + useEffect(() => { + const handleStorageChange = () => { + const updatedMissions = JSON.parse(localStorage.getItem("missions")) || []; + setMissions(updatedMissions); + }; + + window.addEventListener("storage", handleStorageChange); + + return () => { + window.removeEventListener("storage", handleStorageChange); + }; + }, []); + + // ✅ Gestion des accordéons + const handleAccordionChange = (panel) => (event, isExpanded) => { + setExpanded(isExpanded ? panel : false); + }; + return ( - + {/* Left Column */} - {/* Titre et sous-titre */} - + {constructTitle}{" "} - + {constructSubtitle} - {/* Secteurs */} - + Secteurs : {constructSector} - + - {/* Cadre résumé */} - + - + @@ -103,54 +118,36 @@ const ConstructSection = ({ {/* Right Column */} - - - {missionTitle} - - - - {missionItems.map((item, index) => ( - + + {/* ✅ Correction de la duplication du titre */} + {missionTitle && ( + + {missionTitle} + + )} + + {/* ✅ Accordéon dynamique */} + {missions.length > 0 ? ( + missions.map((mission, index) => ( + + }> + {mission.title} + + + {mission.details} + + + )) + ) : ( + + Aucune mission définie. + + )} + + {/* Background Image et Items */} + + {missionItems?.map((item, index) => ( + {item.label} ))} @@ -162,4 +159,4 @@ const ConstructSection = ({ ); }; -export default ConstructSection; +export default ConstructSection; \ No newline at end of file diff --git a/frontend/src/components/Pages/GestionPageAccueil.jsx b/frontend/src/components/Pages/GestionPageAccueil.jsx index 2e84d06..e4e9f13 100644 --- a/frontend/src/components/Pages/GestionPageAccueil.jsx +++ b/frontend/src/components/Pages/GestionPageAccueil.jsx @@ -12,6 +12,19 @@ import { CircularProgress, } from "@mui/material"; +// ✅ Fonction pour sauvegarder les missions dans WordPress +const saveMissionsToWordPress = async (missions) => { + try { + const newData = { missions }; // Sauvegarde dans ACF + await updateHomePageACF(13, newData); + + localStorage.setItem("missions", JSON.stringify(missions)); // Sauvegarde locale + console.log("✅ Missions enregistrées dans WordPress et localStorage !"); + } catch (error) { + console.error("❌ Erreur lors de l'enregistrement des missions :", error); + } +}; + const GestionPageAccueil = () => { const navigate = useNavigate(); const [heroTitle, setHeroTitle] = useState(""); @@ -20,6 +33,7 @@ const GestionPageAccueil = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(""); + const [missions, setMissions] = useState([]); // ✅ Vérification de l'authentification (Redirection si non connecté) useEffect(() => { @@ -71,23 +85,24 @@ const GestionPageAccueil = () => { }, []); // ✅ Mise à jour des champs ACF - const handleSave = async () => { - try { - const newData = { - hero_title: heroTitle, - hero_text: heroText, - }; +const handleSave = async () => { + try { + const newData = { + hero_title: heroTitle, // ✅ Enregistre le H1 + hero_text: heroText, // ✅ Enregistre le texte du Hero + mission: missions, // ✅ Enregistre les missions + }; - console.log("📢 Données envoyées pour mise à jour ACF :", newData); - await updateHomePageACF(13, newData); + await updateHomePageACF(13, newData); + localStorage.setItem("missions", JSON.stringify(missions)); // ✅ Sauvegarde locale - setSuccessMessage("✅ Modifications enregistrées avec succès !"); - setTimeout(() => setSuccessMessage(""), 3000); - } catch (error) { - console.error("❌ Erreur mise à jour :", error); - setError("⚠ Impossible de mettre à jour les champs ACF."); - } - }; + setSuccessMessage("✅ Modifications enregistrées avec succès !"); + setTimeout(() => setSuccessMessage(""), 3000); + } catch (error) { + console.error("❌ Erreur mise à jour :", error); + setError("⚠ Impossible de mettre à jour les champs ACF."); + } +}; // ✅ Gérer le téléversement d’une nouvelle image Hero const handleImageUpload = async (event) => { @@ -105,11 +120,69 @@ const GestionPageAccueil = () => { } }; + useEffect(() => { + const storedMissions = JSON.parse(localStorage.getItem("missions")) || [ + { title: "📌 Mission 1", details: "Détails de la mission 1" }, + { title: "📌 Mission 2", details: "Détails de la mission 2" }, + { title: "📌 Mission 3", details: "Détails de la mission 3" }, + ]; + setMissions(storedMissions); + }, []); + + useEffect(() => { + localStorage.setItem("missions", JSON.stringify(missions)); + }, [missions]); + + // ✅ Fonction pour sauvegarder les missions dans WordPress +const saveMissionsToWordPress = async (missions) => { + try { + const newData = { missions }; // Sauvegarde dans ACF + await updateHomePageACF(13, newData); + + localStorage.setItem("missions", JSON.stringify(missions)); // Sauvegarde locale + console.log("✅ Missions enregistrées dans WordPress et localStorage !"); + } catch (error) { + console.error("❌ Erreur lors de l'enregistrement des missions :", error); + } +}; + + // ✅ Ajouter une mission + const addMission = () => { + setMissions([ + ...missions, + { title: "Nouvelle mission", details: "Détails de la nouvelle mission" }, + ]); + }; + + // ✅ Modifier une mission + const updateMission = (index, field, value) => { + const updatedMissions = missions.map((mission, i) => + i === index ? { ...mission, [field]: value } : mission + ); + setMissions(updatedMissions); + }; + + // ✅ Supprimer une mission + const deleteMission = (index) => { + setMissions(missions.filter((_, i) => i !== index)); + }; + return ( - - + + {/* ✅ En-tête */} - + 🏠 Gestion de la Page d'Accueil @@ -160,7 +233,12 @@ const GestionPageAccueil = () => { )} {/* ✅ Bouton pour changer l'image */} - @@ -195,7 +273,7 @@ const GestionPageAccueil = () => { mt: 3, fontSize: "1.1rem", fontWeight: "bold", - color:"#ffffff", + color: "#ffffff", backgroundColor: "#0e467f", "&:hover": { backgroundColor: "#093a6b" }, }} @@ -209,16 +287,74 @@ const GestionPageAccueil = () => { variant="outlined" color="secondary" fullWidth - sx={{ mt: 2, fontSize: "1rem", fontWeight: "bold", borderColor: "#0e467f", color: "#0e467f" }} + sx={{ + mt: 2, + fontSize: "1rem", + fontWeight: "bold", + borderColor: "#0e467f", + color: "#0e467f", + }} onClick={() => navigate("/admin/dashboard")} > ⬅ Retour au Dashboard )} + + {/* ✅ Gestion de l'Accordéon */} + + + Gestion de l'Accordéon page d'accueil + + + {missions.map((mission, index) => ( + + updateMission(index, "title", e.target.value)} + /> + + updateMission(index, "details", e.target.value) + } + /> + + + ))} + + + ); }; -export default GestionPageAccueil; \ No newline at end of file +export default GestionPageAccueil; diff --git a/frontend/src/components/Pages/Post.jsx b/frontend/src/components/Pages/Post.jsx index cc9e894..53d0b19 100644 --- a/frontend/src/components/Pages/Post.jsx +++ b/frontend/src/components/Pages/Post.jsx @@ -55,7 +55,7 @@ const Posts = () => { return ( - Nos Articles + IN3 Bureau d'études & Maîtrise d'oeuvre diff --git a/frontend/stats.html b/frontend/stats.html new file mode 100644 index 0000000..e12798e --- /dev/null +++ b/frontend/stats.html @@ -0,0 +1,4949 @@ + + + + + + + + Rollup Visualizer + + + +
+ + + + + diff --git a/server/wp-content/themes/hello-elementor-child/functions.php b/server/wp-content/themes/hello-elementor-child/functions.php index 2556a83..9dcf88f 100644 --- a/server/wp-content/themes/hello-elementor-child/functions.php +++ b/server/wp-content/themes/hello-elementor-child/functions.php @@ -289,4 +289,19 @@ add_action('rest_api_init', function () { 'schema' => null, ] ); -}); \ No newline at end of file +}); + +// accordeon +function update_acf_mission($post, $request) { + if (!function_exists('update_field')) { + return; + } + + $params = $request->get_json_params(); + + if (isset($params['mission']) && is_array($params['mission'])) { + update_field('mission', $params['mission'], $post->ID); + } +} + +add_action('rest_after_insert_page', 'update_acf_mission', 10, 2); \ No newline at end of file