Files
Octopus-React-Wp/frontend/src/components/ServicePageTemplate.jsx
T
2025-02-03 03:53:44 +01:00

253 lines
9.0 KiB
React

import { useState } from "react";
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";
import "swiper/css/navigation";
import "swiper/css/pagination";
import PropTypes from "prop-types";
import { Helmet } from "react-helmet-async";
const ServicePageTemplate = ({
title,
subtitle,
interestTitle,
description,
desirTitle,
features,
image,
ctaText,
ctaLink,
carouselItems,
seo, // ✅ Ajout de l'objet SEO
}) => {
const [openModal, setOpenModal] = useState(false);
const [modalContent, setModalContent] = useState({});
const [loadingImage, setLoadingImage] = useState(true);
const handleCardClick = (feature) => {
setModalContent({
title: feature.title,
text: feature.modalText || "Texte non disponible.",
image: feature.modalImage || "https://picsum.photos/id/43/800/400.webp",
});
setLoadingImage(true);
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
return (
<Box sx={{ backgroundColor: "#f5f5f5", color: "#333", fontFamily: "Arial, sans-serif" }}>
{/* ✅ SEO META TAGS */}
<Helmet>
<title>{seo?.metaTitle || title}</title>
<meta name="description" content={seo?.metaDescription || ""} />
<meta name="keywords" content={seo?.keywords || ""} />
<meta property="og:title" content={seo?.metaTitle || title} />
<meta property="og:description" content={seo?.metaDescription || ""} />
<meta property="og:image" content={seo?.ogImage || image} />
<meta property="og:type" content="website" />
<meta name="twitter:title" content={seo?.metaTitle || title} />
<meta name="twitter:description" content={seo?.metaDescription || ""} />
<meta name="twitter:image" content={seo?.ogImage || image} />
<meta name="twitter:card" content="summary_large_image" />
</Helmet>
{/* Section Hero */}
<Box
sx={{
mt:5,
backgroundImage: `url(${image})`,
backgroundSize: "cover",
backgroundPosition: "center",
minHeight: "70vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
color: "black",
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" } }}>
{title}
</Typography>
<Typography variant="body1" sx={{ mb: 4 }}>
{subtitle}
</Typography>
<Button
href={ctaLink}
variant="contained"
color="secondary"
size="large"
sx={{ textTransform: "none", fontWeight: "bold", backgroundColor: "#0e467f", "&:hover": { backgroundColor: "#00bcd4" } }}
>
{ctaText}
</Button>
</Box>
</Box>
{/* 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" }}>
{interestTitle}
</Typography>
<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" } }}>
{desirTitle}
</Typography>
<Grid container spacing={4} justifyContent="center">
{features.map((feature, index) => (
<Grid item xs={12} md={4} key={index}>
<Card
onClick={() => handleCardClick(feature)}
sx={{
cursor: "pointer",
textAlign: "center",
padding: "20px",
backgroundColor: "#f9f9f9",
transition: "0.3s",
"&:hover": { transform: "scale(1.05)", boxShadow: 5 },
}}
>
<CardContent>
<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>
</CardContent>
</Card>
</Grid>
))}
</Grid>
</Box>
{/* Modal */}
<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 }}>
{loadingImage && <CircularProgress sx={{ mb: 2 }} />}
<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>
<Button onClick={handleCloseModal} variant="contained" color="secondary">
Retour
</Button>
</Box>
</Fade>
</Modal>
{/* Carousel Section */}
{carouselItems && carouselItems.length > 0 && (
<Box
sx={{
padding: "40px 20px",
textAlign: "center",
backgroundColor: "#f9f9f9",
}}
>
<Typography variant="h2"
sx={{
marginBottom: 4,
fontSize: { xs: '2rem', md: '3rem', lg: '3rem' }, // Responsive
}}
>
Découvrez nos réalisations
</Typography>
<Swiper
modules={[Navigation, Pagination, Autoplay]}
spaceBetween={20}
slidesPerView={1}
navigation
pagination={{ clickable: true }}
autoplay={{ delay: 3000 }}
loop
>
{carouselItems.map((item, index) => (
<SwiperSlide key={index}>
<Card
sx={{
display: "flex",
alignItems: "center",
padding: "20px",
boxShadow: 3,
}}
>
<img
src={item.image}
alt={item.title}
style={{
width: "40%",
height: "auto",
objectFit: "cover",
borderRadius: "8px",
marginRight: "20px",
}}
/>
<CardContent>
<Typography variant="h3"
sx={{
fontWeight: "bold",
fontSize: { xs: '1.2rem', md: '2rem', lg: '2.5rem' }, // Responsive
}}
>
{item.title}
</Typography>
<Typography variant="body2">{item.description}</Typography>
</CardContent>
</Card>
</SwiperSlide>
))}
</Swiper>
</Box>
)}
</Box>
);
};
// ✅ Définition des types des props avec PropTypes
ServicePageTemplate.propTypes = {
title: PropTypes.string.isRequired,
subtitle: PropTypes.string.isRequired,
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,
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 })),
seo: PropTypes.object, // ✅ Ajout du SEO en option
};
// ✅ Valeurs par défaut
ServicePageTemplate.defaultProps = {
carouselItems: [],
seo: {}, // ✅ SEO par défaut vide
};
export default ServicePageTemplate;