MAJ PAGES SERVICES
This commit is contained in:
@@ -197,6 +197,15 @@ const Header = () => {
|
||||
Systeme Sécurité Incendie (SSI)
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
component={Link}
|
||||
to="/services/expertises-tce"
|
||||
onClick={handleMenuClose}
|
||||
>
|
||||
<WorkIcon sx={{ marginRight: 1}} />
|
||||
expertises-tce
|
||||
</MenuItem>
|
||||
|
||||
</Menu>
|
||||
|
||||
<Button
|
||||
@@ -397,6 +406,18 @@ const Header = () => {
|
||||
<ListItemText primary="SSI..." />
|
||||
</ListItem>
|
||||
|
||||
<ListItem
|
||||
button
|
||||
component={Link}
|
||||
to="/services/expertises-tce"
|
||||
selected={location.pathname.includes(
|
||||
"/services/expertises-tce"
|
||||
)}
|
||||
>
|
||||
<WorkIcon sx={{ marginRight: 0.5 }} />
|
||||
<ListItemText primary="Expertises-tce" />
|
||||
</ListItem>
|
||||
|
||||
<ListItem
|
||||
button
|
||||
component={Link}
|
||||
|
||||
@@ -10,8 +10,11 @@ import {
|
||||
Button,
|
||||
Paper,
|
||||
CircularProgress,
|
||||
Grid,
|
||||
} from "@mui/material";
|
||||
import { Add, Delete, ArrowBack, Save } from "@mui/icons-material";
|
||||
import ReactQuill from "react-quill";
|
||||
import "react-quill/dist/quill.snow.css"; // Import du style de l'éditeur
|
||||
|
||||
function EditPageACF() {
|
||||
const { id } = useParams();
|
||||
@@ -21,14 +24,14 @@ function EditPageACF() {
|
||||
const [error, setError] = useState(null);
|
||||
const [successMessage, setSuccessMessage] = useState("");
|
||||
|
||||
// ✅ Vérifier l'authentification
|
||||
// ✅ Vérification de l'authentification
|
||||
useEffect(() => {
|
||||
if (!getToken()) {
|
||||
navigate("/admin/login");
|
||||
}
|
||||
}, [navigate]);
|
||||
|
||||
// ✅ Récupérer les champs ACF de la page
|
||||
// ✅ Récupération des champs ACF de la page
|
||||
useEffect(() => {
|
||||
const fetchPage = async () => {
|
||||
console.log("📢 Récupération de la page avec ID :", id);
|
||||
@@ -41,13 +44,11 @@ function EditPageACF() {
|
||||
|
||||
try {
|
||||
const pageData = await getPageById(id);
|
||||
|
||||
if (!pageData || !pageData.acf) {
|
||||
setError("❌ Impossible de charger les champs ACF.");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setAcfFields(pageData.acf);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
@@ -62,7 +63,6 @@ function EditPageACF() {
|
||||
// ✅ Mise à jour des champs ACF
|
||||
const handleUpdateACF = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
await updatePageACF(id, acfFields);
|
||||
setSuccessMessage("✅ Modifications enregistrées !");
|
||||
@@ -73,7 +73,7 @@ function EditPageACF() {
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ Gérer la modification des champs ACF
|
||||
// ✅ Gestion des champs ACF
|
||||
const handleFieldChange = (field, value) => {
|
||||
setAcfFields((prevFields) => ({
|
||||
...prevFields,
|
||||
@@ -81,7 +81,7 @@ function EditPageACF() {
|
||||
}));
|
||||
};
|
||||
|
||||
// ✅ Gérer la FAQ : ajouter, modifier et supprimer des entrées
|
||||
// ✅ Gestion des champs FAQ
|
||||
const handleFAQChange = (index, field, value) => {
|
||||
const updatedFAQ = [...(acfFields.faq?.faq_list || [])];
|
||||
updatedFAQ[index][field] = value;
|
||||
@@ -104,12 +104,9 @@ function EditPageACF() {
|
||||
const deleteFAQ = (index) => {
|
||||
const updatedFAQList = acfFields.faq.faq_list.filter((_, i) => i !== index);
|
||||
const updatedACF = { ...acfFields, faq: { ...acfFields.faq, faq_list: updatedFAQList } };
|
||||
|
||||
// Si la FAQ devient vide, on la supprime entièrement pour éviter l'affichage
|
||||
if (updatedFAQList.length === 0) {
|
||||
delete updatedACF.faq.faq_list;
|
||||
}
|
||||
|
||||
setAcfFields(updatedACF);
|
||||
};
|
||||
|
||||
@@ -127,7 +124,7 @@ function EditPageACF() {
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
>
|
||||
<Container maxWidth="sm">
|
||||
<Container maxWidth="md">
|
||||
<Paper elevation={6} sx={{ padding: 4, borderRadius: 3, mt: 10 }}>
|
||||
<Button
|
||||
startIcon={<ArrowBack />}
|
||||
@@ -148,43 +145,49 @@ function EditPageACF() {
|
||||
|
||||
<form onSubmit={handleUpdateACF}>
|
||||
{/* ✅ Affichage dynamique des champs ACF sauf la FAQ */}
|
||||
|
||||
{Object.keys(acfFields)
|
||||
.filter((field) => field !== "faq" && field !== "faq_list") // 🔥 On exclut la FAQ et faq_list
|
||||
.map((field) => (
|
||||
<TextField
|
||||
key={field}
|
||||
label={field.replace(/_/g, " ")}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={acfFields[field] || ""}
|
||||
onChange={(e) => handleFieldChange(field, e.target.value)}
|
||||
sx={{ mb: 2, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{Object.keys(acfFields)
|
||||
.filter((field) => field !== "faq" && field !== "faq_list")
|
||||
.map((field) => (
|
||||
<Grid item xs={12} md={6} key={field}>
|
||||
<Typography variant="h6" sx={{ fontWeight: "bold", mb: 1 }}>
|
||||
{field.replace(/_/g, " ")}
|
||||
</Typography>
|
||||
|
||||
{/* Utiliser l'éditeur WYSIWYG pour les champs texte enrichi */}
|
||||
{field.includes("content") || field.includes("description") ? (
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
value={acfFields[field] || ""}
|
||||
onChange={(value) => handleFieldChange(field, value)}
|
||||
style={{ backgroundColor: "#fff", borderRadius: "5px", marginBottom: "16px" }}
|
||||
/>
|
||||
) : (
|
||||
<TextField
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={acfFields[field] || ""}
|
||||
onChange={(e) => handleFieldChange(field, e.target.value)}
|
||||
sx={{ backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
{/* ✅ Gestion de la FAQ uniquement si elle est définie */}
|
||||
{acfFields.faq?.faq_list && acfFields.faq.faq_list.length > 0 && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: "bold", mb: 1 }}>FAQ</Typography>
|
||||
<Box sx={{ mt: 4 }}>
|
||||
<Typography variant="h5" sx={{ fontWeight: "bold", mb: 2 }}>📌 FAQ</Typography>
|
||||
{acfFields.faq.faq_list.map((item, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
sx={{
|
||||
border: "1px solid #ccc",
|
||||
padding: 2,
|
||||
borderRadius: 2,
|
||||
mb: 2,
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Paper key={index} sx={{ padding: 2, mb: 2 }}>
|
||||
<TextField
|
||||
label="Question"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={item.question || ""}
|
||||
onChange={(e) => handleFAQChange(index, "question", e.target.value)}
|
||||
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
sx={{ mb: 1 }}
|
||||
/>
|
||||
<TextField
|
||||
label="Réponse"
|
||||
@@ -194,25 +197,23 @@ function EditPageACF() {
|
||||
rows={3}
|
||||
value={item.answer || ""}
|
||||
onChange={(e) => handleFAQChange(index, "answer", e.target.value)}
|
||||
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
/>
|
||||
<Button
|
||||
startIcon={<Delete />}
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => deleteFAQ(index)}
|
||||
sx={{ position: "absolute", top: 10, right: 10 }}
|
||||
sx={{ mt: 1 }}
|
||||
>
|
||||
Supprimer
|
||||
</Button>
|
||||
</Box>
|
||||
</Paper>
|
||||
))}
|
||||
<Button startIcon={<Add />} variant="contained" color="primary" onClick={addFAQ} sx={{ mb: 2 }}>
|
||||
<Button startIcon={<Add />} variant="contained" color="primary" onClick={addFAQ}>
|
||||
Ajouter une question
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
<Button type="submit" variant="contained" color="primary" fullWidth startIcon={<Save />} sx={{ mt: 3 }}>
|
||||
Enregistrer les modifications
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import ServicePageTemplate from "../ServicePageTemplate";
|
||||
import { getPageById } from "../../wordpress";
|
||||
|
||||
const ServiceCinq = () => {
|
||||
const [acfData, setAcfData] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const pageId = 612; // 🔥 Remplace par l'ID réel de la page WordPress
|
||||
|
||||
useEffect(() => {
|
||||
const fetchACFData = async () => {
|
||||
try {
|
||||
const pageData = await getPageById(pageId);
|
||||
setAcfData(pageData.acf);
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur récupération des champs ACF :", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchACFData();
|
||||
}, []);
|
||||
|
||||
// ✅ Affichage du chargement en attendant les données ACF
|
||||
if (loading) {
|
||||
return <p>Chargement...</p>;
|
||||
}
|
||||
|
||||
const serviceDetails = {
|
||||
// Hero
|
||||
title: acfData?.titre_principal_tce || "Titre héros !", // ✅ Modifiable individuellement
|
||||
subtitle: acfData?.description_principal_tce || "Description, héros", // ✅ Modifiable individuellement
|
||||
|
||||
image: "https://picsum.photos/id/1021/1920/1080.webp",
|
||||
ctaText: "En savoir plus",
|
||||
ctaLink: "/contact",
|
||||
|
||||
// section 1
|
||||
interestTitle: acfData?.second_titre_tce || "Titre interet", // ✅ Modifiable individuellement
|
||||
description: acfData?.second_description_tce || "Description interet", // ✅ Modifiable individuellement
|
||||
|
||||
// section 2
|
||||
desirTitle: "Titre", // ✅ Modifiable individuellement
|
||||
|
||||
features: [
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/300/800/400.webp",
|
||||
},
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/301/800/400.webp",
|
||||
},
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/302/800/400.webp",
|
||||
},
|
||||
],
|
||||
|
||||
carouselItems: [
|
||||
{
|
||||
title: "Portfolio Modern",
|
||||
description: "Montrez vos compétences avec un portfolio unique.",
|
||||
image: "https://picsum.photos/id/305/800/400.webp",
|
||||
},
|
||||
{
|
||||
title: "Blog SEO",
|
||||
description: "Optimisez vos articles pour le référencement.",
|
||||
image: "https://picsum.photos/id/306/800/400.webp",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return <ServicePageTemplate {...serviceDetails} />;
|
||||
};
|
||||
|
||||
export default ServiceCinq;
|
||||
@@ -30,7 +30,7 @@ const ServiceQuatre = () => {
|
||||
const serviceDetails = {
|
||||
// Hero
|
||||
title: acfData?.titre_principal || "Titre héros !", // ✅ Modifiable individuellement
|
||||
subtitle: acfData?.description_principal || "Description, héros", // ✅ Modifiable individuellement
|
||||
subtitle: <span dangerouslySetInnerHTML={{ __html: acfData?.description_principal || "Description, héros" }} />,
|
||||
|
||||
image: "https://picsum.photos/id/1021/1920/1080.webp",
|
||||
ctaText: "En savoir plus",
|
||||
@@ -38,28 +38,27 @@ const ServiceQuatre = () => {
|
||||
|
||||
// section 1
|
||||
interestTitle: acfData?.second_titre || "Titre interet", // ✅ Modifiable individuellement
|
||||
description: acfData?.second_description || "Description interet", // ✅ Modifiable individuellement
|
||||
|
||||
description: <span dangerouslySetInnerHTML={{ __html: acfData?.second_description || "Description interet" }} />,
|
||||
// section 2
|
||||
desirTitle: "Titre", // ✅ Modifiable individuellement
|
||||
|
||||
features: [
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
title: acfData?.titre_carte_one || "Titre !",
|
||||
description: acfData?.description_carte_one || "Description.",
|
||||
modalText: acfData?.description_carte_one || "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/300/800/400.webp",
|
||||
},
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
title: acfData?.titre_carte_two || "Titre !",
|
||||
description: acfData?.description_carte_two || "Description.",
|
||||
modalText: acfData?.description_carte_two || "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/301/800/400.webp",
|
||||
},
|
||||
{
|
||||
title: "Titre",
|
||||
description: "Description.",
|
||||
modalText: "Description Modal.",
|
||||
title: acfData?.titre_carte_tree || "Titre !",
|
||||
description: acfData?.description_carte_tree || "Description.",
|
||||
modalText: acfData?.description_carte_tree || "Description Modal.",
|
||||
modalImage: "https://picsum.photos/id/302/800/400.webp",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { Box, Typography, Button, Grid, Card, CardContent, Modal, Fade, Backdrop, CircularProgress } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Button,
|
||||
Grid,
|
||||
Card,
|
||||
CardContent,
|
||||
Modal,
|
||||
Fade,
|
||||
Backdrop,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Navigation, Pagination, Autoplay } from "swiper/modules";
|
||||
import "swiper/css";
|
||||
@@ -40,7 +51,13 @@ const ServicePageTemplate = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: "#f5f5f5", color: "#333", fontFamily: "Arial, sans-serif" }}>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#f5f5f5",
|
||||
color: "#333",
|
||||
fontFamily: "Arial, sans-serif",
|
||||
}}
|
||||
>
|
||||
{/* ✅ SEO META TAGS */}
|
||||
<Helmet>
|
||||
<title>{seo?.metaTitle || title}</title>
|
||||
@@ -59,7 +76,7 @@ const ServicePageTemplate = ({
|
||||
{/* Section Hero */}
|
||||
<Box
|
||||
sx={{
|
||||
mt:5,
|
||||
mt: 5,
|
||||
backgroundImage: `url(${image})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
@@ -72,13 +89,27 @@ const ServicePageTemplate = ({
|
||||
padding: "20px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{
|
||||
maxWidth: "800px",
|
||||
backgroundColor:"rgba(255, 255, 255, 0.39)",
|
||||
p:5,
|
||||
borderRadius:5
|
||||
}}>
|
||||
<Typography variant="h1" sx={{ fontWeight: "bold", mb: 2, fontSize: { xs: "2rem", md: "3rem", lg: "3rem",whiteSpace: "pre-line" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: "800px",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.39)",
|
||||
p: 5,
|
||||
borderRadius: 5,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="h1"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
mb: 2,
|
||||
fontSize: {
|
||||
xs: "2rem",
|
||||
md: "3rem",
|
||||
lg: "3rem",
|
||||
whiteSpace: "pre-line",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mb: 4 }}>
|
||||
@@ -89,7 +120,12 @@ const ServicePageTemplate = ({
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
size="large"
|
||||
sx={{ textTransform: "none", fontWeight: "bold", backgroundColor: "#0e467f", "&:hover": { backgroundColor: "#00bcd4" } }}
|
||||
sx={{
|
||||
textTransform: "none",
|
||||
fontWeight: "bold",
|
||||
backgroundColor: "#0e467f",
|
||||
"&:hover": { backgroundColor: "#00bcd4" },
|
||||
}}
|
||||
>
|
||||
{ctaText}
|
||||
</Button>
|
||||
@@ -98,17 +134,41 @@ const ServicePageTemplate = ({
|
||||
|
||||
{/* Section numero 1 */}
|
||||
<Box sx={{ padding: "40px 20px", textAlign: "center" }}>
|
||||
<Typography variant="h2" sx={{ fontWeight: "bold", mb: 2, fontSize: { xs: "2rem", md: "2rem", lg: "2rem" }, whiteSpace: "pre-line" }}>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
mb: 2,
|
||||
fontSize: { xs: "2rem", md: "2rem", lg: "2rem" },
|
||||
whiteSpace: "pre-line",
|
||||
}}
|
||||
>
|
||||
{interestTitle}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ maxWidth: "1000px", margin: "0 auto", mb: 4, whiteSpace: "pre-line" }}>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
maxWidth: "1000px",
|
||||
margin: "0 auto",
|
||||
mb: 4,
|
||||
whiteSpace: "pre-line",
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Section numero 2 */}
|
||||
<Box sx={{ backgroundColor: "#ffffff", padding: "40px 20px" }}>
|
||||
<Typography variant="h2" sx={{ fontWeight: "bold", textAlign: "center", mb: 4, fontSize: { xs: "2rem", md: "3rem", lg: "2rem" } }}>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
textAlign: "center",
|
||||
mb: 4,
|
||||
fontSize: { xs: "2rem", md: "3rem", lg: "2rem" },
|
||||
}}
|
||||
>
|
||||
{desirTitle}
|
||||
</Typography>
|
||||
|
||||
@@ -127,12 +187,27 @@ const ServicePageTemplate = ({
|
||||
}}
|
||||
>
|
||||
<CardContent>
|
||||
<Typography variant="h3" sx={{ fontWeight: "bold", mb: 2, fontSize: 26,whiteSpace: "pre-line" }}>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
mb: 2,
|
||||
fontSize: 26,
|
||||
whiteSpace: "pre-line",
|
||||
}}
|
||||
>
|
||||
{feature.title}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: "#555" }}>
|
||||
{feature.description}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "#555" }}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
feature.description.length > 100
|
||||
? `${feature.description.substring(0, 100)}...`
|
||||
: feature.description,
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
@@ -141,25 +216,58 @@ const ServicePageTemplate = ({
|
||||
</Box>
|
||||
|
||||
{/* Modal */}
|
||||
<Modal open={openModal} onClose={handleCloseModal} closeAfterTransition BackdropComponent={Backdrop} BackdropProps={{ timeout: 500 }}>
|
||||
<Modal
|
||||
open={openModal}
|
||||
onClose={handleCloseModal}
|
||||
closeAfterTransition
|
||||
BackdropComponent={Backdrop}
|
||||
BackdropProps={{ timeout: 500 }}
|
||||
>
|
||||
<Fade in={openModal}>
|
||||
<Box sx={{ position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: "90%", maxWidth: "600px", p: 4, textAlign: "center", background: "white", borderRadius: 2, boxShadow: 3 }}>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "90%",
|
||||
maxWidth: "600px",
|
||||
p: 4,
|
||||
textAlign: "center",
|
||||
background: "white",
|
||||
borderRadius: 2,
|
||||
boxShadow: 3,
|
||||
}}
|
||||
>
|
||||
{loadingImage && <CircularProgress sx={{ mb: 2 }} />}
|
||||
<img src={modalContent.image} alt={modalContent.title} style={{ width: "100%", borderRadius: "8px", display: loadingImage ? "none" : "block" }} onLoad={() => setLoadingImage(false)} />
|
||||
<img
|
||||
src={modalContent.image}
|
||||
alt={modalContent.title}
|
||||
style={{
|
||||
width: "100%",
|
||||
borderRadius: "8px",
|
||||
display: loadingImage ? "none" : "block",
|
||||
}}
|
||||
onLoad={() => setLoadingImage(false)}
|
||||
/>
|
||||
<Typography variant="h3" sx={{ fontWeight: "bold", mb: 2 }}>
|
||||
{modalContent.title}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mb: 4 }}>
|
||||
{modalContent.text}
|
||||
<Typography variant="body1" sx={{ mb: 4 }} dangerouslySetInnerHTML={{ __html: modalContent.text }} >
|
||||
|
||||
</Typography>
|
||||
<Button onClick={handleCloseModal} variant="contained" color="secondary">
|
||||
<Button
|
||||
onClick={handleCloseModal}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
>
|
||||
Retour
|
||||
</Button>
|
||||
</Box>
|
||||
</Fade>
|
||||
</Modal>
|
||||
{/* Carousel Section */}
|
||||
{carouselItems && carouselItems.length > 0 && (
|
||||
{/* Carousel Section */}
|
||||
{carouselItems && carouselItems.length > 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
padding: "40px 20px",
|
||||
@@ -167,11 +275,11 @@ const ServicePageTemplate = ({
|
||||
backgroundColor: "#f9f9f9",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h2"
|
||||
sx={{
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
marginBottom: 4,
|
||||
fontSize: { xs: '2rem', md: '3rem', lg: '3rem' }, // Responsive
|
||||
|
||||
fontSize: { xs: "2rem", md: "3rem", lg: "3rem" }, // Responsive
|
||||
}}
|
||||
>
|
||||
Découvrez nos réalisations
|
||||
@@ -208,10 +316,11 @@ const ServicePageTemplate = ({
|
||||
}}
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography variant="h3"
|
||||
sx={{
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
fontSize: { xs: '1.2rem', md: '2rem', lg: '2.5rem' }, // Responsive
|
||||
fontSize: { xs: "1.2rem", md: "2rem", lg: "2.5rem" }, // Responsive
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
@@ -224,7 +333,6 @@ const ServicePageTemplate = ({
|
||||
</Swiper>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -236,11 +344,24 @@ ServicePageTemplate.propTypes = {
|
||||
interestTitle: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
desirTitle: PropTypes.string.isRequired,
|
||||
features: PropTypes.arrayOf(PropTypes.shape({ title: PropTypes.string.isRequired, description: PropTypes.string.isRequired, modalText: PropTypes.string, modalImage: PropTypes.string })).isRequired,
|
||||
features: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
modalText: PropTypes.string,
|
||||
modalImage: PropTypes.string,
|
||||
})
|
||||
).isRequired,
|
||||
image: PropTypes.string.isRequired,
|
||||
ctaText: PropTypes.string.isRequired,
|
||||
ctaLink: PropTypes.string.isRequired,
|
||||
carouselItems: PropTypes.arrayOf(PropTypes.shape({ title: PropTypes.string.isRequired, description: PropTypes.string.isRequired, image: PropTypes.string.isRequired })),
|
||||
carouselItems: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
image: PropTypes.string.isRequired,
|
||||
})
|
||||
),
|
||||
seo: PropTypes.object, // ✅ Ajout du SEO en option
|
||||
};
|
||||
|
||||
@@ -250,4 +371,4 @@ ServicePageTemplate.defaultProps = {
|
||||
seo: {}, // ✅ SEO par défaut vide
|
||||
};
|
||||
|
||||
export default ServicePageTemplate;
|
||||
export default ServicePageTemplate;
|
||||
|
||||
Reference in New Issue
Block a user