MAJ fonction BO page accueil et correction de beug
This commit is contained in:
+5
-5
@@ -2,20 +2,20 @@
|
|||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>bureau d’études Maîtrise d’oeuvre</title>
|
<title>Centre de formations - metier du numérique</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<!-- ✅ Ajout Open Graph statique -->
|
<!-- ✅ Ajout Open Graph statique -->
|
||||||
<meta property="og:title" content="Titre par défaut - Bureau d’études">
|
<meta property="og:title" content="Titre par défaut - Centre de formations">
|
||||||
<meta property="og:description" content="Bienvenue sur notre bureau d’études en Maîtrise d’œuvre.">
|
<meta property="og:description" content="Bienvenue sur notre Centre de formations aux métiers du numérique.">
|
||||||
<meta property="og:image" content="https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif">
|
<meta property="og:image" content="https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif">
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:url" content="https://ton-site.com">
|
<meta property="og:url" content="https://ton-site.com">
|
||||||
|
|
||||||
<!-- ✅ Twitter Cards -->
|
<!-- ✅ Twitter Cards -->
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
<meta name="twitter:title" content="Titre par défaut - Bureau d’études">
|
<meta name="twitter:title" content="Titre par défaut - Centre de formations">
|
||||||
<meta name="twitter:description" content="Bienvenue sur notre bureau d’études en Maîtrise d’œuvre.">
|
<meta name="twitter:description" content="Bienvenue sur notre Centre de formations aux métiers du numérique.">
|
||||||
<meta name="twitter:image" content="https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif">
|
<meta name="twitter:image" content="https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif">
|
||||||
<!-- <link rel="preload" href="/src/assets/vendor-BFTbvl5C.js" as="script"> -->
|
<!-- <link rel="preload" href="/src/assets/vendor-BFTbvl5C.js" as="script"> -->
|
||||||
<link rel="preload" href="/assets/index-CfManBR6.css" as="style">
|
<link rel="preload" href="/assets/index-CfManBR6.css" as="style">
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap');
|
||||||
|
|
||||||
|
h1{
|
||||||
|
font-size: 3.2em;
|
||||||
|
line-height: 1.1;
|
||||||
|
font-family: "Nunito", sans-serif !important;
|
||||||
|
font-optical-sizing: auto;
|
||||||
|
font-weight: 800 !important;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
@@ -147,7 +147,7 @@ const ConstructSection = ({
|
|||||||
mt: 4,
|
mt: 4,
|
||||||
backgroundColor: "#0e467f",
|
backgroundColor: "#0e467f",
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px 0 12px 12px",
|
||||||
boxShadow: "0 8px 20px rgba(0, 0, 0, 0.1)",
|
boxShadow: "0 8px 20px rgba(0, 0, 0, 0.1)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { getToken } from "../auth";
|
import { getToken } from "../auth";
|
||||||
import { getPageById, updatePageACF } from "../wordpress";
|
import { getPageById, updatePageACF } from "../wordpress";
|
||||||
@@ -15,7 +15,7 @@ import { Add, Delete, ArrowBack, Save } from "@mui/icons-material";
|
|||||||
import ReactQuill from "react-quill";
|
import ReactQuill from "react-quill";
|
||||||
import "react-quill/dist/quill.snow.css";
|
import "react-quill/dist/quill.snow.css";
|
||||||
|
|
||||||
const ETUDE_PAGE_ID = 272; // ✅ ID de la page Bureau d'Étude
|
const ETUDE_PAGE_ID = 272;
|
||||||
|
|
||||||
function EditPageEtude() {
|
function EditPageEtude() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -24,189 +24,195 @@ function EditPageEtude() {
|
|||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [successMessage, setSuccessMessage] = useState("");
|
const [successMessage, setSuccessMessage] = useState("");
|
||||||
|
|
||||||
// ✅ Vérification de l'authentification
|
// Vérifie l'authentification
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!getToken()) {
|
if (!getToken()) navigate("/admin/login");
|
||||||
navigate("/admin/login");
|
|
||||||
}
|
|
||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
// ✅ Récupération des champs ACF
|
// Récupère les champs ACF
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPage = async () => {
|
const fetchPage = async () => {
|
||||||
try {
|
try {
|
||||||
const pageData = await getPageById(ETUDE_PAGE_ID);
|
const pageData = await getPageById(ETUDE_PAGE_ID);
|
||||||
if (!pageData || !pageData.acf) {
|
if (!pageData?.acf) {
|
||||||
setError("❌ Impossible de charger les champs ACF.");
|
setError("❌ Impossible de charger les champs ACF.");
|
||||||
setLoading(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log("expertises_specifiques:", pageData.acf.expertises_specifiques);
|
||||||
setAcfFields(pageData.acf);
|
setAcfFields(pageData.acf);
|
||||||
} catch (error) {
|
} catch {
|
||||||
setError("⚠ Impossible de récupérer les champs ACF.");
|
setError("⚠ Impossible de récupérer les champs ACF.");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPage();
|
fetchPage();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ✅ Mise à jour des champs ACF
|
// Mise à jour ACF
|
||||||
const handleUpdateACF = async (e) => {
|
const handleUpdateACF = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
try {
|
try {
|
||||||
await updatePageACF(ETUDE_PAGE_ID, acfFields);
|
await updatePageACF(ETUDE_PAGE_ID, acfFields);
|
||||||
setSuccessMessage("✅ Modifications enregistrées !");
|
setSuccessMessage("✅ Modifications enregistrées !");
|
||||||
|
setError(null);
|
||||||
setTimeout(() => navigate("/admin/dashboard"), 2000);
|
setTimeout(() => navigate("/admin/dashboard"), 2000);
|
||||||
} catch (error) {
|
} catch {
|
||||||
setError("⚠ Impossible de mettre à jour les champs ACF.");
|
setError("⚠ Impossible de mettre à jour les champs ACF.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Gestion des champs ACF
|
// Modifie un champ simple
|
||||||
const handleFieldChange = (field, value) => {
|
const handleFieldChange = (field, value) => {
|
||||||
setAcfFields((prevFields) => ({
|
setAcfFields(prev => ({ ...prev, [field]: value }));
|
||||||
...prevFields,
|
|
||||||
[field]: value,
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Gestion des répéteurs
|
// Normalise un repeater en tableau
|
||||||
|
const getRepeater = (field) => {
|
||||||
|
const data = acfFields[field];
|
||||||
|
return Array.isArray(data)
|
||||||
|
? data
|
||||||
|
: data
|
||||||
|
? Object.values(data)
|
||||||
|
: [];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modifie un item du repeater
|
||||||
const handleRepeaterChange = (field, index, subField, value) => {
|
const handleRepeaterChange = (field, index, subField, value) => {
|
||||||
const updatedList = [...acfFields[field]];
|
const list = getRepeater(field);
|
||||||
updatedList[index][subField] = value;
|
const updated = [...list];
|
||||||
setAcfFields({ ...acfFields, [field]: updatedList });
|
updated[index] = { ...updated[index], [subField]: value };
|
||||||
|
setAcfFields(prev => ({ ...prev, [field]: updated }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ajoute un item au repeater
|
||||||
const addRepeaterItem = (field, template) => {
|
const addRepeaterItem = (field, template) => {
|
||||||
setAcfFields({
|
const list = getRepeater(field);
|
||||||
...acfFields,
|
setAcfFields(prev => ({ ...prev, [field]: [...list, template] }));
|
||||||
[field]: [...(acfFields[field] || []), template],
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Supprime un item du repeater
|
||||||
const deleteRepeaterItem = (field, index) => {
|
const deleteRepeaterItem = (field, index) => {
|
||||||
const updatedList = acfFields[field].filter((_, i) => i !== index);
|
const list = getRepeater(field);
|
||||||
setAcfFields({ ...acfFields, [field]: updatedList });
|
const updated = list.filter((_, i) => i !== index);
|
||||||
|
setAcfFields(prev => ({ ...prev, [field]: updated }));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) return <Typography>Chargement...</Typography>;
|
if (loading) return <Typography>Chargement...</Typography>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box sx={{ py: 4, backgroundColor: "#f5f5f5" }}>
|
||||||
sx={{
|
|
||||||
minHeight: "100vh",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
backgroundColor: "#f5f5f5",
|
|
||||||
padding: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Container maxWidth="md">
|
<Container maxWidth="md">
|
||||||
<Paper elevation={6} sx={{ padding: 4, borderRadius: 3 }}>
|
<Paper sx={{ p: 4, borderRadius: 3 }} elevation={4}>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<ArrowBack />}
|
startIcon={<ArrowBack />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
|
||||||
onClick={() => navigate("/admin/dashboard")}
|
onClick={() => navigate("/admin/dashboard")}
|
||||||
sx={{ mb: 2 }}
|
sx={{ mb: 2 }}
|
||||||
>
|
>
|
||||||
Retour à la gestion des pages
|
Retour
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
<Typography variant="h4" sx={{ fontWeight: "bold", mb: 3, textAlign: "center" }}>
|
||||||
Modifier la Page Bureau d'Étude
|
Modifier la Page Bureau d'Étude
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{error && <Typography color="error" sx={{ mb: 2 }}>{error}</Typography>}
|
{error && <Typography color="error" sx={{ mb: 2 }}>{error}</Typography>}
|
||||||
{successMessage && <Typography sx={{ color: "green", textAlign: "center", mb: 2 }}>{successMessage}</Typography>}
|
{successMessage && <Typography color="success.main" sx={{ mb: 2, textAlign: "center" }}>{successMessage}</Typography>}
|
||||||
|
|
||||||
<form onSubmit={handleUpdateACF}>
|
<form onSubmit={handleUpdateACF}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={3}>
|
||||||
{/* ✅ Introduction */}
|
{/* Introduction */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold" }}>Introduction</Typography>
|
<Typography variant="h6">Introduction</Typography>
|
||||||
<ReactQuill
|
<ReactQuill
|
||||||
theme="snow"
|
|
||||||
value={acfFields.introduction || ""}
|
value={acfFields.introduction || ""}
|
||||||
onChange={(value) => handleFieldChange("introduction", value)}
|
onChange={(val) => handleFieldChange("introduction", val)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* ✅ Méthodologie */}
|
{/* Méthodologie */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold" }}>Méthodologie</Typography>
|
<Typography variant="h6">Méthodologie</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
|
||||||
value={acfFields.methodologie || ""}
|
value={acfFields.methodologie || ""}
|
||||||
onChange={(e) => handleFieldChange("methodologie", e.target.value)}
|
onChange={(e) => handleFieldChange("methodologie", e.target.value)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* ✅ Liste des compétences */}
|
{/* Liste des compétences */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold" }}>Liste des compétences</Typography>
|
<Typography variant="h6">Liste des compétences</Typography>
|
||||||
{acfFields.liste_des_competences?.map((item, index) => (
|
{getRepeater("liste_des_competences").map((item, i) => (
|
||||||
<Paper key={index} sx={{ padding: 2, mb: 2 }}>
|
<Paper key={i} sx={{ p:2, mb:2 }}>
|
||||||
<TextField
|
<TextField
|
||||||
label="Titre"
|
label="Titre"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={item.comp_titre}
|
value={item.comp_titre}
|
||||||
onChange={(e) => handleRepeaterChange("liste_des_competences", index, "comp_titre", e.target.value)}
|
onChange={(e) => handleRepeaterChange("liste_des_competences", i, "comp_titre", e.target.value)}
|
||||||
sx={{ mb:1 }}
|
sx={{ mb:1 }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label="Description"
|
label="Description"
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline rows={3}
|
||||||
rows={3}
|
|
||||||
value={item.comp_description}
|
value={item.comp_description}
|
||||||
onChange={(e) => handleRepeaterChange("liste_des_competences", index, "comp_description", e.target.value)}
|
onChange={(e) => handleRepeaterChange("liste_des_competences", i, "comp_description", e.target.value)}
|
||||||
|
sx={{ mb:1 }}
|
||||||
/>
|
/>
|
||||||
<Button startIcon={<Delete />} variant="outlined" color="error" onClick={() => deleteRepeaterItem("liste_des_competences", index)}>
|
<Button startIcon={<Delete />} variant="outlined" color="error" onClick={() => deleteRepeaterItem("liste_des_competences", i)}>
|
||||||
Supprimer
|
Supprimer
|
||||||
</Button>
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
<Button startIcon={<Add />} variant="contained" color="primary" onClick={() => addRepeaterItem("liste_des_competences", { comp_titre: "", comp_description: "" })}>
|
<Button startIcon={<Add />} variant="contained" onClick={() => addRepeaterItem("liste_des_competences", { comp_titre: "", comp_description: "" })}>
|
||||||
Ajouter une compétence
|
Ajouter une compétence
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* ✅ Expertises spécifiques */}
|
{/* Expertises spécifiques */}
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold" }}>Expertises spécifiques</Typography>
|
<Typography variant="h6">Expertises spécifiques</Typography>
|
||||||
{acfFields.expertises_specifiques?.map((item, index) => (
|
{getRepeater("expertises_specifiques").map((item, i) => (
|
||||||
<Paper key={index} sx={{ padding: 2, mb: 2 }}>
|
<Paper key={i} sx={{ p:2, mb:2 }}>
|
||||||
<TextField
|
<TextField
|
||||||
label="Nom"
|
label="Nom"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={item.expertise_nom}
|
value={item.expertise_nom}
|
||||||
onChange={(e) => handleRepeaterChange("expertises_specifiques", index, "expertise_nom", e.target.value)}
|
onChange={(e) => handleRepeaterChange("expertises_specifiques", i, "expertise_nom", e.target.value)}
|
||||||
sx={{ mb:1 }}
|
sx={{ mb:1 }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label="Détails"
|
label="Détails"
|
||||||
fullWidth
|
fullWidth multiline rows={2}
|
||||||
multiline
|
|
||||||
rows={2}
|
|
||||||
value={item.expertise_details}
|
value={item.expertise_details}
|
||||||
onChange={(e) => handleRepeaterChange("expertises_specifiques", index, "expertise_details", e.target.value)}
|
onChange={(e) => handleRepeaterChange("expertises_specifiques", i, "expertise_details", e.target.value)}
|
||||||
|
sx={{ mb:1 }}
|
||||||
/>
|
/>
|
||||||
<Button startIcon={<Delete />} variant="outlined" color="error" onClick={() => deleteRepeaterItem("expertises_specifiques", index)}>
|
<Button startIcon={<Delete />} variant="outlined" color="error" onClick={() => deleteRepeaterItem("expertises_specifiques", i)}>
|
||||||
Supprimer
|
Supprimer
|
||||||
</Button>
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
<Button startIcon={<Add />} variant="contained" onClick={() => addRepeaterItem("expertises_specifiques", { expertise_nom: "", expertise_details: "" })}>
|
||||||
|
Ajouter une expertise
|
||||||
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Button type="submit" variant="contained" color="primary" fullWidth startIcon={<Save />} sx={{ mt: 3 }}>
|
{/* Save */}
|
||||||
Enregistrer les modifications
|
<Grid item xs={12}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
fullWidth
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<Save />}
|
||||||
|
sx={{ py:1.5 }}
|
||||||
|
>
|
||||||
|
Enregistrer
|
||||||
</Button>
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import ArticleIcon from "@mui/icons-material/Article";
|
|||||||
import InfoIcon from "@mui/icons-material/Info";
|
import InfoIcon from "@mui/icons-material/Info";
|
||||||
import ContactMailIcon from "@mui/icons-material/ContactMail";
|
import ContactMailIcon from "@mui/icons-material/ContactMail";
|
||||||
import WorkIcon from "@mui/icons-material/Work";
|
import WorkIcon from "@mui/icons-material/Work";
|
||||||
import Logo from "../assets/logo-in3.svg";
|
import Logo from "../assets/centre-formation-logo.avif";
|
||||||
import LogoM from "../assets/logo-in3-mobil.svg";
|
import LogoM from "../assets/centre-formation-logo.avif";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||||
@@ -123,7 +123,7 @@ const Header = () => {
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={Logo}
|
src={Logo}
|
||||||
alt="Bureau d'études Le Mans"
|
alt="centre de formation numérique"
|
||||||
style={{
|
style={{
|
||||||
width: "50px",
|
width: "50px",
|
||||||
height: "50px",
|
height: "50px",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Typography, Button } from '@mui/material';
|
import { Box, Typography, Button } from '@mui/material';
|
||||||
|
|
||||||
|
|
||||||
const Hero = ({ backgroundImage, useGradient, title, titleColor, text, textColor }) => {
|
const Hero = ({ backgroundImage, useGradient, title, titleColor, text, textColor }) => {
|
||||||
// Priorité pour appliquer le fond : Image > Dégradé > Aucun fond
|
// Priorité pour appliquer le fond : Image > Dégradé > Aucun fond
|
||||||
const backgroundStyle = backgroundImage
|
const backgroundStyle = backgroundImage
|
||||||
@@ -60,9 +61,10 @@ const Hero = ({ backgroundImage, useGradient, title, titleColor, text, textColor
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
padding: { xs: '10px 20px', md: '15px 30px' }, // Responsive
|
padding: { xs: '10px 20px', md: '15px 30px' }, // Responsive
|
||||||
fontSize: { xs: '0.8rem', md: '1rem' },
|
fontSize: { xs: '0.8rem', md: '1rem' },
|
||||||
|
backgroundColor: '#315397',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Explorer les Articles
|
Nos Formations
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ const About = () => {
|
|||||||
mb: 4, mt:5
|
mb: 4, mt:5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
La société IN3
|
La société IN3 !!!
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Typography,
|
Typography,
|
||||||
@@ -15,26 +15,31 @@ const BureauEtudes = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPageData = async () => {
|
const fetchPageData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.get("wp/v2/pages/272?_fields=acf"); // Remplace XXX par l'ID WordPress de la page
|
const response = await api.get("wp/v2/pages/272?_fields=acf");
|
||||||
|
console.log("expertises_specifiques:", response.data.acf.expertises_specifiques);
|
||||||
setPageData(response.data.acf);
|
setPageData(response.data.acf);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error("Erreur lors de la récupération des données ACF :", error);
|
||||||
"Erreur lors de la récupération des données ACF :",
|
|
||||||
error
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPageData();
|
fetchPageData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const expertises = useMemo(() => {
|
||||||
|
if (!pageData?.expertises_specifiques) return [];
|
||||||
|
return Array.isArray(pageData.expertises_specifiques)
|
||||||
|
? pageData.expertises_specifiques
|
||||||
|
: Object.values(pageData.expertises_specifiques);
|
||||||
|
}, [pageData]);
|
||||||
|
|
||||||
if (!pageData) {
|
if (!pageData) {
|
||||||
return <Typography>Chargement...</Typography>;
|
return <Typography>Chargement...</Typography>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{}}>
|
<Box>
|
||||||
{/* Section Héros avec Image de Fond */}
|
{/* Section Héros */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
backgroundImage: "url('https://picsum.photos/1920/600.webp')",
|
backgroundImage: "url('https://picsum.photos/1920/600.webp')",
|
||||||
@@ -50,29 +55,32 @@ const BureauEtudes = () => {
|
|||||||
px: 4,
|
px: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
{/* Présentation Générale */}
|
{/* Présentation Générale */}
|
||||||
<Box sx={{ mt: 6, textAlign: "center", px: 4 }}>
|
<Box sx={{ mt: 6, textAlign: "center", px: 4 }}>
|
||||||
<Typography variant="h1" sx={{
|
<Typography
|
||||||
fontSize: { xs: "3rem", md: "3rem", lg: "3.5rem" }, // Responsive
|
variant="h1"
|
||||||
|
sx={{
|
||||||
|
fontSize: { xs: "3rem", md: "3rem", lg: "3.5rem" },
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
mb: 2,
|
mb: 2,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Notre Bureau d'Études
|
Notre Bureau d'Études
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{ maxWidth: "900px", mx: "auto" }}
|
<Typography
|
||||||
dangerouslySetInnerHTML={{ __html: pageData.introduction }}>
|
variant="body2"
|
||||||
|
sx={{ maxWidth: "900px", mx: "auto" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: pageData.introduction }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
{/* Domaines d'Intervention */}
|
{/* Domaines d'Intervention */}
|
||||||
<Box sx={{ mt: 6, px: 4 }}>
|
<Box sx={{ mt: 6, px: 4 }}>
|
||||||
<Typography variant="h2" sx={{
|
<Typography
|
||||||
fontSize: { xs: "2.5rem", md: "2.5rem", lg: "2.5rem" }, // Responsive
|
variant="h2"
|
||||||
fontWeight: "bold",
|
sx={{ fontSize: "2.5rem", fontWeight: "bold", textAlign: "center", mb: 3 }}
|
||||||
textAlign: "center",
|
>
|
||||||
mb: 3 }}>
|
|
||||||
Nos Domaines d'Intervention
|
Nos Domaines d'Intervention
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={4} justifyContent="center">
|
<Grid container spacing={4} justifyContent="center">
|
||||||
@@ -90,16 +98,15 @@ const BureauEtudes = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h3" sx={{
|
<Typography
|
||||||
fontWeight: "bold",
|
variant="h3"
|
||||||
mb: 1,
|
sx={{ fontWeight: "bold", mb: 1, fontSize: "1.8rem" }}
|
||||||
fontSize: { xs: "1.8rem", md: "1.8rem", lg: "1.8rem" }, // Responsive
|
>
|
||||||
}}>
|
|
||||||
{competence.comp_titre}
|
{competence.comp_titre}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{
|
<Typography variant="body2" sx={{ textAlign: "center" }}>
|
||||||
textAlign:"center"
|
{competence.comp_description}
|
||||||
}}>{competence.comp_description}</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -109,11 +116,7 @@ const BureauEtudes = () => {
|
|||||||
|
|
||||||
{/* Compétences Spécifiques */}
|
{/* Compétences Spécifiques */}
|
||||||
<Box sx={{ mt: 6, textAlign: "center", px: 4 }}>
|
<Box sx={{ mt: 6, textAlign: "center", px: 4 }}>
|
||||||
<Typography variant="h2" sx={{
|
<Typography variant="h2" sx={{ fontSize: "2.5rem", fontWeight: "bold", mb: 3 }}>
|
||||||
fontSize: { xs: "2.5rem", md: "2.5rem", lg: "2.5rem" }, // Responsive
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 3
|
|
||||||
}}>
|
|
||||||
Nos Compétences
|
Nos Compétences
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" sx={{ maxWidth: "900px", mx: "auto" }}>
|
<Typography variant="body1" sx={{ maxWidth: "900px", mx: "auto" }}>
|
||||||
@@ -132,15 +135,12 @@ const BureauEtudes = () => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h2" sx={{
|
<Typography variant="h2" sx={{ fontSize: "2.5rem", fontWeight: "bold", mb: 3 }}>
|
||||||
fontSize: { xs: "2.5rem", md: "2.5rem", lg: "2.5rem" }, // Responsive
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 3
|
|
||||||
}}>
|
|
||||||
Engagement et Accompagnement
|
Engagement et Accompagnement
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={4} justifyContent="center">
|
<Grid container spacing={4} justifyContent="center">
|
||||||
{pageData.expertises_specifiques?.map((expertise, index) => (
|
{expertises.length > 0 ? (
|
||||||
|
expertises.map((expertise, index) => (
|
||||||
<Grid item xs={12} sm={6} md={4} key={index}>
|
<Grid item xs={12} sm={6} md={4} key={index}>
|
||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
@@ -156,17 +156,19 @@ const BureauEtudes = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h3" sx={{
|
<Typography variant="h3" sx={{ fontSize: "1.8rem", fontWeight: "bold", mb: 1 }}>
|
||||||
fontSize: { xs: "1.8rem", md: "1.8rem", lg: "1.8rem" }, // Responsive
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 1 }}>
|
|
||||||
{expertise.expertise_nom}
|
{expertise.expertise_nom}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{expertise.expertise_details}</Typography>
|
<Typography variant="body2">
|
||||||
|
{expertise.expertise_details}
|
||||||
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<Typography>Aucune expertise spécifique à afficher.</Typography>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
@@ -12,19 +12,6 @@ import {
|
|||||||
CircularProgress,
|
CircularProgress,
|
||||||
} from "@mui/material";
|
} 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 GestionPageAccueil = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [heroTitle, setHeroTitle] = useState("");
|
const [heroTitle, setHeroTitle] = useState("");
|
||||||
@@ -35,14 +22,20 @@ const GestionPageAccueil = () => {
|
|||||||
const [successMessage, setSuccessMessage] = useState("");
|
const [successMessage, setSuccessMessage] = useState("");
|
||||||
const [missions, setMissions] = useState([]);
|
const [missions, setMissions] = useState([]);
|
||||||
|
|
||||||
// ✅ Vérification de l'authentification (Redirection si non connecté)
|
const [constructTitle, setConstructTitle] = useState("");
|
||||||
|
const [constructSubtitle, setConstructSubtitle] = useState("");
|
||||||
|
const [constructSector, setConstructSector] = useState("");
|
||||||
|
const [constructNote, setConstructNote] = useState("");
|
||||||
|
const [constructText, setConstructText] = useState("");
|
||||||
|
|
||||||
|
// ✅ Redirection si non connecté
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
navigate("/admin/login");
|
navigate("/admin/login");
|
||||||
}
|
}
|
||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
// ✅ Chargement des données ACF depuis WordPress
|
// ✅ Chargement des données ACF
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPageData = async () => {
|
const fetchPageData = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -64,7 +57,7 @@ const GestionPageAccueil = () => {
|
|||||||
setHeroTitle(data.acf?.hero_title || "");
|
setHeroTitle(data.acf?.hero_title || "");
|
||||||
setHeroText(data.acf?.hero_text || "");
|
setHeroText(data.acf?.hero_text || "");
|
||||||
|
|
||||||
// ✅ Récupération de l'image Hero
|
// ✅ Image Hero
|
||||||
if (data.acf?.img_hero) {
|
if (data.acf?.img_hero) {
|
||||||
const mediaResponse = await fetch(
|
const mediaResponse = await fetch(
|
||||||
`https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/media/${data.acf.img_hero}`
|
`https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/media/${data.acf.img_hero}`
|
||||||
@@ -73,6 +66,13 @@ const GestionPageAccueil = () => {
|
|||||||
setHeroImage(mediaData.source_url);
|
setHeroImage(mediaData.source_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ GDC Construct
|
||||||
|
setConstructTitle(data.acf?.gdc_construct?.construct_title || "");
|
||||||
|
setConstructSubtitle(data.acf?.gdc_construct?.construct_subtitle || "");
|
||||||
|
setConstructSector(data.acf?.gdc_construct?.construct_sector || "");
|
||||||
|
setConstructNote(data.acf?.gdc_construct?.construct_note || "");
|
||||||
|
setConstructText(data.acf?.gdc_construct?.construct_text || "");
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ Erreur chargement ACF :", error);
|
console.error("❌ Erreur chargement ACF :", error);
|
||||||
@@ -84,18 +84,24 @@ const GestionPageAccueil = () => {
|
|||||||
fetchPageData();
|
fetchPageData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ✅ Mise à jour des champs ACF
|
// ✅ Enregistrement ACF
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
try {
|
try {
|
||||||
const newData = {
|
const newData = {
|
||||||
hero_title: heroTitle, // ✅ Enregistre le H1
|
hero_title: heroTitle,
|
||||||
hero_text: heroText, // ✅ Enregistre le texte du Hero
|
hero_text: heroText,
|
||||||
mission: missions, // ✅ Enregistre les missions
|
mission: missions,
|
||||||
|
gdc_construct: {
|
||||||
|
construct_title: constructTitle,
|
||||||
|
construct_subtitle: constructSubtitle,
|
||||||
|
construct_sector: constructSector,
|
||||||
|
construct_note: constructNote,
|
||||||
|
construct_text: constructText,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await updateHomePageACF(13, newData);
|
await updateHomePageACF(13, newData);
|
||||||
localStorage.setItem("missions", JSON.stringify(missions)); // ✅ Sauvegarde locale
|
localStorage.setItem("missions", JSON.stringify(missions));
|
||||||
|
|
||||||
setSuccessMessage("✅ Modifications enregistrées avec succès !");
|
setSuccessMessage("✅ Modifications enregistrées avec succès !");
|
||||||
setTimeout(() => setSuccessMessage(""), 3000);
|
setTimeout(() => setSuccessMessage(""), 3000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -104,22 +110,23 @@ const GestionPageAccueil = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Gérer le téléversement d’une nouvelle image Hero
|
// ✅ Upload image
|
||||||
const handleImageUpload = async (event) => {
|
const handleImageUpload = async (event) => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
try {
|
try {
|
||||||
const imageId = await uploadImage(file);
|
const imageId = await uploadImage(file);
|
||||||
setHeroImage(URL.createObjectURL(file)); // Affichage immédiat
|
setHeroImage(URL.createObjectURL(file));
|
||||||
await updateHomePageACF(13, { img_hero: imageId });
|
await updateHomePageACF(13, { img_hero: imageId });
|
||||||
setSuccessMessage("✅ Image mise à jour !");
|
setSuccessMessage("✅ Image mise à jour !");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ Erreur lors de l'upload :", error);
|
console.error("❌ Erreur upload image :", error);
|
||||||
setError("❌ Échec de l'upload de l'image.");
|
setError("❌ Échec de l'upload de l'image.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ✅ Missions - LocalStorage
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedMissions = JSON.parse(localStorage.getItem("missions")) || [
|
const storedMissions = JSON.parse(localStorage.getItem("missions")) || [
|
||||||
{ title: "📌 Mission 1", details: "Détails de la mission 1" },
|
{ title: "📌 Mission 1", details: "Détails de la mission 1" },
|
||||||
@@ -133,20 +140,6 @@ const GestionPageAccueil = () => {
|
|||||||
localStorage.setItem("missions", JSON.stringify(missions));
|
localStorage.setItem("missions", JSON.stringify(missions));
|
||||||
}, [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 = () => {
|
const addMission = () => {
|
||||||
setMissions([
|
setMissions([
|
||||||
...missions,
|
...missions,
|
||||||
@@ -154,7 +147,6 @@ const GestionPageAccueil = () => {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Modifier une mission
|
|
||||||
const updateMission = (index, field, value) => {
|
const updateMission = (index, field, value) => {
|
||||||
const updatedMissions = missions.map((mission, i) =>
|
const updatedMissions = missions.map((mission, i) =>
|
||||||
i === index ? { ...mission, [field]: value } : mission
|
i === index ? { ...mission, [field]: value } : mission
|
||||||
@@ -162,7 +154,6 @@ const GestionPageAccueil = () => {
|
|||||||
setMissions(updatedMissions);
|
setMissions(updatedMissions);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Supprimer une mission
|
|
||||||
const deleteMission = (index) => {
|
const deleteMission = (index) => {
|
||||||
setMissions(missions.filter((_, i) => i !== index));
|
setMissions(missions.filter((_, i) => i !== index));
|
||||||
};
|
};
|
||||||
@@ -173,7 +164,6 @@ const GestionPageAccueil = () => {
|
|||||||
elevation={6}
|
elevation={6}
|
||||||
sx={{ padding: 4, borderRadius: 3, backgroundColor: "#f8f9fa" }}
|
sx={{ padding: 4, borderRadius: 3, backgroundColor: "#f8f9fa" }}
|
||||||
>
|
>
|
||||||
{/* ✅ En-tête */}
|
|
||||||
<Typography
|
<Typography
|
||||||
variant="h4"
|
variant="h4"
|
||||||
sx={{
|
sx={{
|
||||||
@@ -186,7 +176,6 @@ const GestionPageAccueil = () => {
|
|||||||
🏠 Gestion de la Page d'Accueil
|
🏠 Gestion de la Page d'Accueil
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* ✅ Affichage du statut de chargement */}
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Box display="flex" justifyContent="center" alignItems="center">
|
<Box display="flex" justifyContent="center" alignItems="center">
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
@@ -197,7 +186,6 @@ const GestionPageAccueil = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* ✅ Message de succès */}
|
|
||||||
{successMessage && (
|
{successMessage && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -216,7 +204,6 @@ const GestionPageAccueil = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ✅ Affichage de l'image actuelle */}
|
|
||||||
{heroImage && (
|
{heroImage && (
|
||||||
<Box sx={{ textAlign: "center", mb: 2 }}>
|
<Box sx={{ textAlign: "center", mb: 2 }}>
|
||||||
<img
|
<img
|
||||||
@@ -232,7 +219,6 @@ const GestionPageAccueil = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ✅ Bouton pour changer l'image */}
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
component="label"
|
component="label"
|
||||||
@@ -243,7 +229,6 @@ const GestionPageAccueil = () => {
|
|||||||
<input type="file" hidden onChange={handleImageUpload} />
|
<input type="file" hidden onChange={handleImageUpload} />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{/* ✅ Formulaire de modification */}
|
|
||||||
<TextField
|
<TextField
|
||||||
label="Titre Héros"
|
label="Titre Héros"
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -266,7 +251,7 @@ const GestionPageAccueil = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ✅ Gestion de l'Accordéon */}
|
{/* ✅ Bloc Missions */}
|
||||||
<Paper elevation={3} sx={{ marginTop: "30px", padding: "20px" }}>
|
<Paper elevation={3} sx={{ marginTop: "30px", padding: "20px" }}>
|
||||||
<Typography variant="h4" sx={{ marginBottom: "10px" }}>
|
<Typography variant="h4" sx={{ marginBottom: "10px" }}>
|
||||||
Gestion de l'Accordéon page d'accueil
|
Gestion de l'Accordéon page d'accueil
|
||||||
@@ -317,8 +302,63 @@ const GestionPageAccueil = () => {
|
|||||||
➕ Ajouter une mission
|
➕ Ajouter une mission
|
||||||
</Button>
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
|
{/* ✅ Bloc Construct */}
|
||||||
|
<Paper elevation={3} sx={{ marginTop: "30px", padding: "20px" }}>
|
||||||
|
<Typography variant="h4" sx={{ marginBottom: "10px" }}>
|
||||||
|
🔧 Zone Formations
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Titre h2"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={constructTitle}
|
||||||
|
onChange={(e) => setConstructTitle(e.target.value)}
|
||||||
|
sx={{ mb: 2 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Sous-titre h2"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={constructSubtitle}
|
||||||
|
onChange={(e) => setConstructSubtitle(e.target.value)}
|
||||||
|
sx={{ mb: 2 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Secteurs formations"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={constructSector}
|
||||||
|
onChange={(e) => setConstructSector(e.target.value)}
|
||||||
|
sx={{ mb: 2 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Texte Construct"
|
||||||
|
fullWidth
|
||||||
|
multiline
|
||||||
|
rows={4}
|
||||||
|
variant="outlined"
|
||||||
|
value={constructText}
|
||||||
|
onChange={(e) => setConstructText(e.target.value)}
|
||||||
|
sx={{ mb: 2 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Note formation"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={constructNote}
|
||||||
|
onChange={(e) => setConstructNote(e.target.value)}
|
||||||
|
sx={{ mb: 2 }}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* ✅ Actions */}
|
||||||
<Paper elevation={3} sx={{ marginTop: "30px", padding: "20px" }}>
|
<Paper elevation={3} sx={{ marginTop: "30px", padding: "20px" }}>
|
||||||
{/* ✅ Bouton d'enregistrement */}
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -336,7 +376,6 @@ const GestionPageAccueil = () => {
|
|||||||
💾 Enregistrer les modifications
|
💾 Enregistrer les modifications
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{/* ✅ Bouton retour au Dashboard */}
|
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ import ModernSpinner from "../SpinnerModerne";
|
|||||||
import Expertises from "../Expertises";
|
import Expertises from "../Expertises";
|
||||||
import ConstructSection from "../ConstructSection";
|
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";
|
import Logo from "../../assets/centre-formation-logo.avif";
|
||||||
import Testi from "../Testi";
|
import Testi from "../Testi";
|
||||||
|
import '../../assets/style.css';
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const [pageData, setPageData] = useState(null);
|
const [pageData, setPageData] = useState(null);
|
||||||
@@ -72,8 +73,8 @@ const Home = () => {
|
|||||||
{/* SEO */}
|
{/* SEO */}
|
||||||
<SEO
|
<SEO
|
||||||
postId={13} // ID WordPress valide
|
postId={13} // ID WordPress valide
|
||||||
defaultTitle={rank_math_title || "Bureau d'études & Maîtrise d'oeuvre"}
|
defaultTitle={rank_math_title || "centre de formation "}
|
||||||
defaultDescription={rank_math_description || "L'acteur indispensable pour vos projets de constructions"}
|
defaultDescription={rank_math_description || "formation et reconversion professionnelle dans les métiers du numérique"}
|
||||||
defaultCanonicalUrl={acf?.canonical_url || window.location.href}
|
defaultCanonicalUrl={acf?.canonical_url || window.location.href}
|
||||||
defaultOgImage={heroImage || "https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif"}
|
defaultOgImage={heroImage || "https://preprod.octopusdesign.fr/api-octopus/server/wp-content/uploads/2025/01/Construction-logements-au-Mans-01.avif"}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+4949
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user