maj template page
This commit is contained in:
Generated
+23
-9
@@ -19,6 +19,7 @@
|
|||||||
"react-helmet-async": "^2.0.5",
|
"react-helmet-async": "^2.0.5",
|
||||||
"react-router-dom": "^7.1.1",
|
"react-router-dom": "^7.1.1",
|
||||||
"react-simple-lightbox": "^1.0.26",
|
"react-simple-lightbox": "^1.0.26",
|
||||||
|
"react-toastify": "^11.0.3",
|
||||||
"simple-react-lightbox": "^3.6.8",
|
"simple-react-lightbox": "^3.6.8",
|
||||||
"svgo": "^3.3.2",
|
"svgo": "^3.3.2",
|
||||||
"swiper": "^10.3.1"
|
"swiper": "^10.3.1"
|
||||||
@@ -3392,6 +3393,15 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cosmiconfig/node_modules/yaml": {
|
||||||
|
"version": "1.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
|
||||||
|
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/create-ecdh": {
|
"node_modules/create-ecdh": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
|
||||||
@@ -9986,6 +9996,19 @@
|
|||||||
"react": "^16.8.3 || ^17 || ^18"
|
"react": "^16.8.3 || ^17 || ^18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-toastify": {
|
||||||
|
"version": "11.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.3.tgz",
|
||||||
|
"integrity": "sha512-cbPtHJPfc0sGqVwozBwaTrTu1ogB9+BLLjd4dDXd863qYLj7DGrQ2sg5RAChjFUB4yc3w8iXOtWcJqPK/6xqRQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "^2.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18 || ^19",
|
||||||
|
"react-dom": "^18 || ^19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
"version": "4.4.5",
|
"version": "4.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||||
@@ -12865,15 +12888,6 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yaml": {
|
|
||||||
"version": "1.10.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
|
|
||||||
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
|
|
||||||
"license": "ISC",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs": {
|
"node_modules/yargs": {
|
||||||
"version": "17.7.2",
|
"version": "17.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"react-helmet-async": "^2.0.5",
|
"react-helmet-async": "^2.0.5",
|
||||||
"react-router-dom": "^7.1.1",
|
"react-router-dom": "^7.1.1",
|
||||||
"react-simple-lightbox": "^1.0.26",
|
"react-simple-lightbox": "^1.0.26",
|
||||||
|
"react-toastify": "^11.0.3",
|
||||||
"simple-react-lightbox": "^3.6.8",
|
"simple-react-lightbox": "^3.6.8",
|
||||||
"svgo": "^3.3.2",
|
"svgo": "^3.3.2",
|
||||||
"swiper": "^10.3.1"
|
"swiper": "^10.3.1"
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ const Expertices = ({
|
|||||||
<Grid item xs={12} md={4}>
|
<Grid item xs={12} md={4}>
|
||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
backgroundPosition: "center",
|
|
||||||
boxShadow: 3,
|
boxShadow: 3,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
@@ -99,7 +98,6 @@ const Expertices = ({
|
|||||||
<Grid item xs={12} md={4}>
|
<Grid item xs={12} md={4}>
|
||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
backgroundPosition: "center",
|
|
||||||
boxShadow: 3,
|
boxShadow: 3,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
@@ -149,7 +147,6 @@ const Expertices = ({
|
|||||||
<Grid item xs={12} md={4}>
|
<Grid item xs={12} md={4}>
|
||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
backgroundPosition: "center",
|
|
||||||
boxShadow: 3,
|
boxShadow: 3,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
@@ -179,7 +179,7 @@ const Header = () => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/services/formation-video"
|
to="/services/electricite"
|
||||||
onClick={handleMenuClose}
|
onClick={handleMenuClose}
|
||||||
>
|
>
|
||||||
<WorkIcon sx={{ marginRight: 1}} />
|
<WorkIcon sx={{ marginRight: 1}} />
|
||||||
@@ -350,25 +350,26 @@ const Header = () => {
|
|||||||
<WorkIcon sx={{ marginRight: 0.5 }} />
|
<WorkIcon sx={{ marginRight: 0.5 }} />
|
||||||
<ListItemText primary="Prestation maitrise oeuvre" />
|
<ListItemText primary="Prestation maitrise oeuvre" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem
|
<ListItem
|
||||||
button
|
button
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/services/formation-ia"
|
to="/services/structure-beton-charpente-metallique-bois"
|
||||||
selected={location.pathname.includes("/services/formation-ia")}
|
selected={location.pathname.includes("/services/structure-beton-charpente-metallique-bois")}
|
||||||
>
|
>
|
||||||
<WorkIcon sx={{ marginRight: 0.5 }} />
|
<WorkIcon sx={{ marginRight: 0.5 }} />
|
||||||
<ListItemText primary="Formation IA" />
|
<ListItemText primary="Structure beton..." />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
button
|
button
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/services/formation-video"
|
to="/services/electricite"
|
||||||
selected={location.pathname.includes(
|
selected={location.pathname.includes(
|
||||||
"/services/formation-video"
|
"/services/electricite"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<WorkIcon sx={{ marginRight: 0.5 }} />
|
<WorkIcon sx={{ marginRight: 0.5 }} />
|
||||||
<ListItemText primary="Formation Video" />
|
<ListItemText primary="Electricité..." />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
button
|
button
|
||||||
|
|||||||
@@ -356,10 +356,9 @@ const Contact = () => {
|
|||||||
<Typography
|
<Typography
|
||||||
variant="h2"
|
variant="h2"
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: { xs: "2rem", md: "2rem", lg: "3rem" }, // Responsive
|
fontSize: { xs: "2rem", md: "2rem", lg: "2rem" }, // Responsive
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
mb: 2,
|
mb: 2,
|
||||||
fontSize: { xs: "1.5rem", md: "2rem" },
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Besoin d'une assistance immédiate ?
|
Besoin d'une assistance immédiate ?
|
||||||
|
|||||||
@@ -1,27 +1,89 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { fetchPosts, deletePost } from "../../wordpress";
|
import { fetchPosts, deletePost } from "../../wordpress";
|
||||||
|
import { Box, Typography, Button, CircularProgress, Paper, Grid } from "@mui/material";
|
||||||
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
|
|
||||||
function PostList() {
|
function PostList() {
|
||||||
const [posts, setPosts] = useState([]);
|
const [posts, setPosts] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function loadPosts() {
|
async function loadPosts() {
|
||||||
|
try {
|
||||||
const data = await fetchPosts();
|
const data = await fetchPosts();
|
||||||
setPosts(data);
|
setPosts(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError("⚠️ Impossible de récupérer les articles.");
|
||||||
|
console.error("Erreur lors de la récupération des articles :", err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadPosts();
|
loadPosts();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleDelete = async (postId) => {
|
||||||
|
if (window.confirm("❌ Es-tu sûr de vouloir supprimer cet article ?")) {
|
||||||
|
try {
|
||||||
|
await deletePost(postId);
|
||||||
|
setPosts(posts.filter((post) => post.id !== postId));
|
||||||
|
toast.success("✅ Article supprimé avec succès !");
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Erreur suppression :", err);
|
||||||
|
toast.error("⚠️ Erreur lors de la suppression.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="post-list">
|
<Box sx={{ maxWidth: "900px", margin: "auto", mt: 5 }}>
|
||||||
<h2>Liste des Articles</h2>
|
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
||||||
|
📋 Liste des Articles
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{loading && (
|
||||||
|
<Box sx={{ textAlign: "center", mt: 4 }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<Typography color="error" textAlign="center" sx={{ mb: 3 }}>
|
||||||
|
{error}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && posts.length === 0 && (
|
||||||
|
<Typography textAlign="center" sx={{ mt: 3 }}>
|
||||||
|
Aucun article trouvé.
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Grid container spacing={3}>
|
||||||
{posts.map((post) => (
|
{posts.map((post) => (
|
||||||
<div key={post.id} className="post-item">
|
<Grid item xs={12} sm={6} md={4} key={post.id}>
|
||||||
<h3>{post.title.rendered}</h3>
|
<Paper sx={{ padding: 3, boxShadow: 3, textAlign: "center" }}>
|
||||||
<button onClick={() => deletePost(post.id)}>Supprimer</button>
|
<Typography variant="h6" sx={{ fontWeight: "bold", mb: 2 }}>
|
||||||
</div>
|
{post.title.rendered}
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
startIcon={<DeleteIcon />}
|
||||||
|
onClick={() => handleDelete(post.id)}
|
||||||
|
sx={{ fontWeight: "bold" }}
|
||||||
|
>
|
||||||
|
Supprimer
|
||||||
|
</Button>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</div>
|
</Grid>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PostList;
|
export default PostList;
|
||||||
@@ -1,50 +1,62 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import ServicePageTemplate from '../ServicePageTemplate';
|
import ServicePageTemplate from "../ServicePageTemplate";
|
||||||
|
|
||||||
const ServiceDeux = () => {
|
const ServiceDeux = () => {
|
||||||
const serviceDetails = {
|
const serviceDetails = {
|
||||||
title: 'Structure béton charpente métallique & bois',
|
// Hero
|
||||||
subtitle: 'Dominez l’intelligence artificielle.',
|
title: "Structure béton charpente métallique & bois",
|
||||||
description:
|
subtitle: "Dominez l’intelligence artificielle.",
|
||||||
'Plongez dans le futur ! Notre formation IA vous prépare aux outils modernes d’intelligence artificielle comme Python, TensorFlow et OpenAI API. Apprenez à créer des modèles IA performants.',
|
|
||||||
|
image: "https://picsum.photos/id/239/1920/1080.webp",
|
||||||
|
ctaText: "Découvrir la formation IA",
|
||||||
|
ctaLink: "/contact",
|
||||||
|
|
||||||
|
// section 1
|
||||||
|
interestTitle: "Béton ou Charpente : Quel Matériau Choisir pour une Construction Durable ?", // ✅ Modifiable individuellement
|
||||||
|
description: "Le béton est le matériau de construction le plus répandu dans le monde. Il est présent dans tous les secteurs de la construction.\n Longtemps associé à l’image négative des grands ensembles, gris et vieillissants, le béton a réalisé des progrès spectaculaires ces dernières années, tant au niveau de ses performances techniques que des aspects esthétiques. Il commence même à entrer dans les foyers comme produit de décoration !<br>Une charpente est un assemblage de pièces de bois et/ou de métal, servant à soutenir ou couvrir des constructions et faisant partie de la toiture.",
|
||||||
|
|
||||||
|
// section 2
|
||||||
|
desirTitle: "Ce que nous offrons",// ✅ Modifiable individuellement
|
||||||
|
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
title: 'Fondamentaux de l’IA',
|
title: "Fondamentaux de l’IA",
|
||||||
description: 'Concepts, algorithmes et applications.',
|
description: "Concepts, algorithmes et applications.",
|
||||||
modalText: 'Découvrez les bases de l’IA, des algorithmes aux applications concrètes dans divers domaines.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/200/800/400.webp',
|
"Découvrez les bases de l’IA, des algorithmes aux applications concrètes dans divers domaines.",
|
||||||
|
modalImage: "https://picsum.photos/id/200/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Python pour l’IA',
|
title: "Python pour l’IA",
|
||||||
description: 'Bibliothèques populaires : TensorFlow, PyTorch.',
|
description: "Bibliothèques populaires : TensorFlow, PyTorch.",
|
||||||
modalText: 'Apprenez à utiliser Python et ses bibliothèques pour concevoir des modèles d’IA puissants.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/201/800/400.webp',
|
"Apprenez à utiliser Python et ses bibliothèques pour concevoir des modèles d’IA puissants.",
|
||||||
|
modalImage: "https://picsum.photos/id/201/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Projets Pratiques',
|
title: "Projets Pratiques",
|
||||||
description: 'Créez vos propres modèles IA.',
|
description: "Créez vos propres modèles IA.",
|
||||||
modalText: 'Mettez vos compétences en pratique en développant des projets IA réels.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/202/800/400.webp',
|
"Mettez vos compétences en pratique en développant des projets IA réels.",
|
||||||
|
modalImage: "https://picsum.photos/id/202/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
image: 'https://picsum.photos/id/239/1920/1080.webp',
|
|
||||||
ctaText: 'Découvrir la formation IA',
|
|
||||||
ctaLink: '/contact',
|
|
||||||
carouselItems: [
|
carouselItems: [
|
||||||
{
|
{
|
||||||
title: 'Site E-commerce',
|
title: "Site E-commerce",
|
||||||
description: 'Un projet e-commerce performant et moderne.',
|
description: "Un projet e-commerce performant et moderne.",
|
||||||
image: 'https://picsum.photos/id/453/800/400.webp',
|
image: "https://picsum.photos/id/453/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Portfolio Personnel',
|
title: "Portfolio Personnel",
|
||||||
description: 'Montrez vos compétences avec un portfolio sur mesure.',
|
description: "Montrez vos compétences avec un portfolio sur mesure.",
|
||||||
image: 'https://picsum.photos/id/454/800/400.webp',
|
image: "https://picsum.photos/id/454/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blog Dynamique',
|
title: "Blog Dynamique",
|
||||||
description: 'Créez un blog interactif et optimisé pour le SEO.',
|
description: "Créez un blog interactif et optimisé pour le SEO.",
|
||||||
image: 'https://picsum.photos/id/455/800/400.webp',
|
image: "https://picsum.photos/id/455/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,52 +1,69 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import ServicePageTemplate from '../ServicePageTemplate';
|
import ServicePageTemplate from "../ServicePageTemplate";
|
||||||
|
|
||||||
const ServiceTrois = () => {
|
const ServiceTrois = () => {
|
||||||
const serviceDetails = {
|
const serviceDetails = {
|
||||||
title: 'Électricité',
|
// Hero
|
||||||
subtitle: 'IN3 est un bureau d’études technique spécialisé dans l’ingénierie électrique du bâtiment.',
|
title: "Électricité", // ✅ Modifiable individuellement
|
||||||
description:
|
subtitle: "IN3 est un bureau d’études technique spécialisé dans l’ingénierie électrique du bâtiment.",
|
||||||
'Plongez dans le futur ! Notre formation IA vous prépare aux outils modernes d’intelligence artificielle comme Python, TensorFlow et OpenAI API. Apprenez à créer des modèles IA performants.',
|
|
||||||
|
image: "https://picsum.photos/id/1018/1920/1080.webp",
|
||||||
|
ctaText: "En savoir plus",
|
||||||
|
ctaLink: "/contact",
|
||||||
|
|
||||||
|
// Section 1
|
||||||
|
interestTitle: "Comment réussir vos installations électriques \navec une assistance experte en maîtrise d’ouvrage ?",
|
||||||
|
description: "Notre activité est l’assistance aux maîtres d’ouvrage à la réalisation des installations électriques courants forts et courants faibles.\n Définition des besoins / Audit si installations existantes Estimation du coût des ouvrages.\n \n Plans d’implantation du matériel et des canalisations schémas électriques unifilaires.\n Analyse des offres et assistance technique au choix de l’entreprise d’électricité.",
|
||||||
|
|
||||||
|
// Section 2
|
||||||
|
desirTitle: "Réalisation et assistance électrique",
|
||||||
|
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
title: 'Chantier électricité industriel',
|
title: "Chantier électricité industriel",
|
||||||
description: 'Réalisation d’installations électriques.',
|
description: "Réalisation d’installations électriques.",
|
||||||
modalText: 'Réalisation d’installations électriques pour des sites industriels, incluant le câblage, la pose d’équipements, et la mise en conformité selon les normes en vigueur..',
|
modalText: "Réalisation d’installations électriques pour des sites industriels, incluant le câblage, la pose d’équipements, et la mise en conformité selon les normes en vigueur.",
|
||||||
modalImage: 'https://picsum.photos/id/200/800/400.webp',
|
modalImage: "https://picsum.photos/id/200/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Python pour l’IA',
|
title: "Dossier de Consultation",
|
||||||
description: 'Bibliothèques populaires : TensorFlow, PyTorch.',
|
description: "Réalisation du Dossier de Consultation des entreprises (DCE)",
|
||||||
modalText: 'Apprenez à utiliser Python et ses bibliothèques pour concevoir des modèles d’IA puissants.',
|
modalText: "Réalisation du Dossier de Consultation des entreprises (DCE) cahier des clauses techniques particulières (CCTP) bordereau de décomposition du prix global et forfaitaire (DPGF, servant de base à tous les devis).",
|
||||||
modalImage: 'https://picsum.photos/id/201/800/400.webp',
|
modalImage: "https://picsum.photos/id/201/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Projets Pratiques',
|
title: "L'électricité & Suivi de chantier",
|
||||||
description: 'Créez vos propres modèles IA.',
|
description: "Assistance à l’entreprise et vérification des documents",
|
||||||
modalText: 'Mettez vos compétences en pratique en développant des projets IA réels.',
|
modalText: "Assistance à l’entreprise et vérification des documents d’exécution. Réception des ouvrages exécutés. Nous pouvons également assister l’entreprise titulaire du marché à la réalisation des documents d’exécution (plans d’implantation, schématique électrique, notes de calculs réglementaires, …)",
|
||||||
modalImage: 'https://picsum.photos/id/202/800/400.webp',
|
modalImage: "https://picsum.photos/id/202/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
image: 'https://picsum.photos/id/239/1920/1080.webp',
|
|
||||||
ctaText: 'En savoir plus !',
|
|
||||||
ctaLink: '/contact',
|
|
||||||
carouselItems: [
|
carouselItems: [
|
||||||
{
|
{
|
||||||
title: 'Site E-commerce',
|
title: "Site E-commerce",
|
||||||
description: 'Un projet e-commerce performant et moderne.',
|
description: "Un projet e-commerce performant et moderne.",
|
||||||
image: 'https://picsum.photos/id/453/800/400.webp',
|
image: "https://picsum.photos/id/453/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Portfolio Personnel',
|
title: "Portfolio Personnel",
|
||||||
description: 'Montrez vos compétences avec un portfolio sur mesure.',
|
description: "Montrez vos compétences avec un portfolio sur mesure.",
|
||||||
image: 'https://picsum.photos/id/454/800/400.webp',
|
image: "https://picsum.photos/id/454/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blog Dynamique',
|
title: "Blog Dynamique",
|
||||||
description: 'Créez un blog interactif et optimisé pour le SEO.',
|
description: "Créez un blog interactif et optimisé pour le SEO.",
|
||||||
image: 'https://picsum.photos/id/455/800/400.webp',
|
image: "https://picsum.photos/id/455/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// ✅ Métadonnées SEO
|
||||||
|
seo: {
|
||||||
|
metaTitle: "Formation Électricité | Expertise en ingénierie électrique",
|
||||||
|
metaDescription: "Découvrez notre expertise en ingénierie électrique et maîtrisez l'installation et la gestion des systèmes électriques.",
|
||||||
|
keywords: "électricité, ingénierie électrique, installation électrique, suivi de chantier",
|
||||||
|
ogImage: "https://picsum.photos/1200/630",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return <ServicePageTemplate {...serviceDetails} />;
|
return <ServicePageTemplate {...serviceDetails} />;
|
||||||
|
|||||||
@@ -1,45 +1,57 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import ServicePageTemplate from '../ServicePageTemplate';
|
import ServicePageTemplate from "../ServicePageTemplate";
|
||||||
|
|
||||||
const ServiceUn = () => {
|
const ServiceUn = () => {
|
||||||
const serviceDetails = {
|
const serviceDetails = {
|
||||||
title: 'Prestation-maitrise-oeuvre',
|
// Hero
|
||||||
subtitle: 'Apprenez à maîtriser les technologies du web.',
|
title: 'Titre héros', // ✅ Modifiable individuellement
|
||||||
description:
|
subtitle: 'Description, héros', // ✅ Modifiable individuellement
|
||||||
'Notre formation web vous permet de développer vos compétences en développement frontend, backend et design. Rejoignez notre programme pour apprendre HTML, CSS, JavaScript et bien plus.',
|
|
||||||
|
image: "https://picsum.photos/id/1018/1920/1080.webp",
|
||||||
|
ctaText: "En savoir plus",
|
||||||
|
ctaLink: "/contact",
|
||||||
|
|
||||||
|
// section 1
|
||||||
|
interestTitle: 'Titre interet', // ✅ Modifiable individuellement
|
||||||
|
description: 'Description interet', // ✅ Modifiable individuellement
|
||||||
|
|
||||||
|
// section 2
|
||||||
|
desirTitle: 'Titre Désir', // ✅ Modifiable individuellement
|
||||||
|
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
title: 'Frontend Development',
|
title: "Frontend Development",
|
||||||
description: 'HTML, CSS, JavaScript, React et plus encore.',
|
description: "HTML, CSS, JavaScript, React et plus encore.",
|
||||||
modalText: 'Apprenez à construire des interfaces utilisateurs modernes avec les technologies frontend.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/300/800/400.webp',
|
"Apprenez à construire des interfaces utilisateurs modernes avec les technologies frontend.",
|
||||||
|
modalImage: "https://picsum.photos/id/300/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Backend Development',
|
title: "Backend Development",
|
||||||
description: 'Node.js, Express, MongoDB et bases de données.',
|
description: "Node.js, Express, MongoDB et bases de données.",
|
||||||
modalText: 'Développez des applications robustes avec des technologies backend performantes.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/301/800/400.webp',
|
"Développez des applications robustes avec des technologies backend performantes.",
|
||||||
|
modalImage: "https://picsum.photos/id/301/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Responsive Design',
|
title: "Responsive Design",
|
||||||
description: 'Apprenez à créer des designs modernes et adaptatifs.',
|
description: "Apprenez à créer des designs modernes et adaptatifs.",
|
||||||
modalText: 'Maîtrisez les principes du responsive design pour des expériences utilisateur optimales.',
|
modalText:
|
||||||
modalImage: 'https://picsum.photos/id/302/800/400.webp',
|
"Maîtrisez les principes du responsive design pour des expériences utilisateur optimales.",
|
||||||
|
modalImage: "https://picsum.photos/id/302/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
image: 'https://picsum.photos/id/1018/1920/1080.webp',
|
|
||||||
ctaText: 'En savoir plus',
|
|
||||||
ctaLink: '/contact',
|
|
||||||
carouselItems: [
|
carouselItems: [
|
||||||
{
|
{
|
||||||
title: 'Portfolio Modern',
|
title: "Portfolio Modern",
|
||||||
description: 'Montrez vos compétences avec un portfolio unique.',
|
description: "Montrez vos compétences avec un portfolio unique.",
|
||||||
image: 'https://picsum.photos/id/305/800/400.webp',
|
image: "https://picsum.photos/id/305/800/400.webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blog SEO',
|
title: "Blog SEO",
|
||||||
description: 'Optimisez vos articles pour le référencement.',
|
description: "Optimisez vos articles pour le référencement.",
|
||||||
image: 'https://picsum.photos/id/306/800/400.webp',
|
image: "https://picsum.photos/id/306/800/400.webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,40 +1,37 @@
|
|||||||
import React, { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import { Box, Typography, Button, Grid, Card, CardContent, Modal, Fade, Backdrop, CircularProgress } from "@mui/material";
|
||||||
Box,
|
|
||||||
Typography,
|
|
||||||
Button,
|
|
||||||
Grid,
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
Modal,
|
|
||||||
Fade,
|
|
||||||
Backdrop,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { Swiper, SwiperSlide } from "swiper/react";
|
import { Swiper, SwiperSlide } from "swiper/react";
|
||||||
import { Navigation, Pagination, Autoplay } from "swiper/modules";
|
import { Navigation, Pagination, Autoplay } from "swiper/modules";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
import "swiper/css/navigation";
|
import "swiper/css/navigation";
|
||||||
import "swiper/css/pagination";
|
import "swiper/css/pagination";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { Helmet } from "react-helmet-async";
|
||||||
|
|
||||||
const ServicePageTemplate = ({
|
const ServicePageTemplate = ({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
interestTitle,
|
||||||
description,
|
description,
|
||||||
|
desirTitle,
|
||||||
features,
|
features,
|
||||||
image,
|
image,
|
||||||
ctaText,
|
ctaText,
|
||||||
ctaLink,
|
ctaLink,
|
||||||
carouselItems,
|
carouselItems,
|
||||||
|
seo, // ✅ Ajout de l'objet SEO
|
||||||
}) => {
|
}) => {
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const [modalContent, setModalContent] = useState({});
|
const [modalContent, setModalContent] = useState({});
|
||||||
|
const [loadingImage, setLoadingImage] = useState(true);
|
||||||
|
|
||||||
const handleCardClick = (feature) => {
|
const handleCardClick = (feature) => {
|
||||||
setModalContent({
|
setModalContent({
|
||||||
title: feature.title,
|
title: feature.title,
|
||||||
text: feature.modalText || "Texte non disponible.",
|
text: feature.modalText || "Texte non disponible.",
|
||||||
image: feature.modalImage || "https://picsum.photos/id/43/800/400.webp", // Image par défaut
|
image: feature.modalImage || "https://picsum.photos/id/43/800/400.webp",
|
||||||
});
|
});
|
||||||
|
setLoadingImage(true);
|
||||||
setOpenModal(true);
|
setOpenModal(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,14 +40,23 @@ const ServicePageTemplate = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box sx={{ backgroundColor: "#f5f5f5", color: "#333", fontFamily: "Arial, sans-serif" }}>
|
||||||
sx={{
|
{/* ✅ SEO META TAGS */}
|
||||||
backgroundColor: "#f5f5f5",
|
<Helmet>
|
||||||
color: "#333",
|
<title>{seo?.metaTitle || title}</title>
|
||||||
fontFamily: "Arial, sans-serif",
|
<meta name="description" content={seo?.metaDescription || ""} />
|
||||||
}}
|
<meta name="keywords" content={seo?.keywords || ""} />
|
||||||
>
|
<meta property="og:title" content={seo?.metaTitle || title} />
|
||||||
{/* Section Attention */}
|
<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
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
backgroundImage: `url(${image})`,
|
backgroundImage: `url(${image})`,
|
||||||
@@ -66,116 +72,56 @@ const ServicePageTemplate = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ maxWidth: "800px" }}>
|
<Box sx={{ maxWidth: "800px" }}>
|
||||||
<Typography
|
<Typography variant="h1" sx={{ fontWeight: "bold", mb: 2, fontSize: { xs: "2rem", md: "3rem", lg: "4rem" } }}>
|
||||||
variant="h1"
|
|
||||||
sx={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 2,
|
|
||||||
fontSize: { xs: '2rem', md: '3rem', lg: '4rem' }, // Responsive
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{title}
|
{title}
|
||||||
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography variant="body1" sx={{ mb: 4 }}>
|
||||||
variant="body1"
|
|
||||||
sx={{
|
|
||||||
mb: 4
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{subtitle}
|
{subtitle}
|
||||||
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button
|
<Button
|
||||||
href={ctaLink}
|
href={ctaLink}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="large"
|
size="large"
|
||||||
sx={{
|
sx={{ textTransform: "none", fontWeight: "bold", backgroundColor: "#0e467f", "&:hover": { backgroundColor: "#00bcd4" } }}
|
||||||
textTransform: "none",
|
|
||||||
fontWeight: "bold",
|
|
||||||
backgroundColor: " #0e467f",
|
|
||||||
"&:hover": { backgroundColor: "#00bcd4" },
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{ctaText}
|
{ctaText}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Section Interest */}
|
{/* Section numero 1 */}
|
||||||
<Box sx={{ padding: "40px 20px", textAlign: "center" }}>
|
<Box sx={{ padding: "40px 20px", textAlign: "center" }}>
|
||||||
<Typography variant="h2"
|
<Typography variant="h2" sx={{ fontWeight: "bold", mb: 2, fontSize: { xs: "2rem", md: "2rem", lg: "2rem" }, whiteSpace: "pre-line" }}>
|
||||||
sx={{
|
{interestTitle}
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 2,
|
|
||||||
fontSize: { xs: '2rem', md: '3rem', lg: '3rem' }, // Responsive
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Pourquoi choisir notre formation ?
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography variant="body1" sx={{ maxWidth: "1000px", margin: "0 auto", mb: 4, whiteSpace: "pre-line" }}>
|
||||||
<Typography
|
|
||||||
variant="body1"
|
|
||||||
sx={{ maxWidth: "800px", margin: "0 auto", mb: 4 }}
|
|
||||||
>
|
|
||||||
{description}
|
{description}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Section Desire */}
|
{/* Section numero 2 */}
|
||||||
<Box sx={{ backgroundColor: "#ffffff", padding: "40px 20px" }}>
|
<Box sx={{ backgroundColor: "#ffffff", padding: "40px 20px" }}>
|
||||||
<Typography
|
<Typography variant="h2" sx={{ fontWeight: "bold", textAlign: "center", mb: 4, fontSize: { xs: "2rem", md: "3rem", lg: "2rem" } }}>
|
||||||
variant="h2"
|
{desirTitle}
|
||||||
sx={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
textAlign: "center",
|
|
||||||
mb: 4,
|
|
||||||
fontSize: { xs: '2rem', md: '3rem', lg: '3rem' }, // Responsive
|
|
||||||
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Ce que nous offrons
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Grid container spacing={4} justifyContent="center">
|
<Grid container spacing={4} justifyContent="center">
|
||||||
{features.map((feature, index) => (
|
{features.map((feature, index) => (
|
||||||
<Grid item xs={12} md={4} key={index}>
|
<Grid item xs={12} md={4} key={index}>
|
||||||
<Card
|
<Card
|
||||||
|
onClick={() => handleCardClick(feature)}
|
||||||
sx={{
|
sx={{
|
||||||
boxShadow: 2,
|
cursor: "pointer",
|
||||||
borderRadius: 2,
|
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
padding: "20px",
|
padding: "20px",
|
||||||
backgroundColor: "#f9f9f9",
|
backgroundColor: "#f9f9f9",
|
||||||
cursor: "pointer",
|
transition: "0.3s",
|
||||||
transition: "transform 0.3s ease, box-shadow 0.3s ease",
|
"&:hover": { transform: "scale(1.05)", boxShadow: 5 },
|
||||||
"&:hover": {
|
|
||||||
transform: {
|
|
||||||
xs: "none", // Pas d'hover sur mobile
|
|
||||||
md: "scale(1.05)", // Hover sur desktop uniquement
|
|
||||||
},
|
|
||||||
boxShadow: {
|
|
||||||
xs: 2, // Pas d'effet de hover sur mobile
|
|
||||||
md: 5, // Augmentation de l'ombre sur desktop
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"&:active": {
|
|
||||||
transform: "scale(0.98)", // Effet de clic pour le tactile
|
|
||||||
boxShadow: 3,
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
onClick={() => handleCardClick(feature)}
|
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography
|
<Typography variant="h3" sx={{ fontWeight: "bold", mb: 2, fontSize: 26 }}>
|
||||||
variant="h3"
|
|
||||||
sx={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 2,
|
|
||||||
fontSize: 26,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{feature.title}
|
{feature.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{ color: "#555" }}>
|
<Typography variant="body2" sx={{ color: "#555" }}>
|
||||||
@@ -189,177 +135,46 @@ const ServicePageTemplate = ({
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Modal */}
|
{/* Modal */}
|
||||||
<Modal
|
<Modal open={openModal} onClose={handleCloseModal} closeAfterTransition BackdropComponent={Backdrop} BackdropProps={{ timeout: 500 }}>
|
||||||
open={openModal}
|
|
||||||
onClose={handleCloseModal}
|
|
||||||
closeAfterTransition
|
|
||||||
BackdropComponent={Backdrop}
|
|
||||||
BackdropProps={{
|
|
||||||
timeout: 500,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Fade in={openModal}>
|
<Fade in={openModal}>
|
||||||
<Box
|
<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 }}>
|
||||||
sx={{
|
{loadingImage && <CircularProgress sx={{ mb: 2 }} />}
|
||||||
position: "absolute",
|
<img src={modalContent.image} alt={modalContent.title} style={{ width: "100%", borderRadius: "8px", display: loadingImage ? "none" : "block" }} onLoad={() => setLoadingImage(false)} />
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
width: "90%",
|
|
||||||
maxWidth: "600px",
|
|
||||||
p: 4,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
background: "rgb(255, 255, 255)",
|
|
||||||
boxShadow: "0 4px 30px rgba(0, 0, 0, 0.1)",
|
|
||||||
backdropFilter: "blur(10px)",
|
|
||||||
borderRadius: 2,
|
|
||||||
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
||||||
color: "rgb(0, 0, 0)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={modalContent.image}
|
|
||||||
alt={modalContent.title}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
borderRadius: "8px",
|
|
||||||
marginBottom: "20px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography variant="h3" sx={{ fontWeight: "bold", mb: 2 }}>
|
<Typography variant="h3" sx={{ fontWeight: "bold", mb: 2 }}>
|
||||||
{modalContent.title}
|
{modalContent.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" sx={{ mb: 4 }}>
|
<Typography variant="body1" sx={{ mb: 4 }}>
|
||||||
{modalContent.text}
|
{modalContent.text}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button
|
<Button onClick={handleCloseModal} variant="contained" color="secondary">
|
||||||
onClick={handleCloseModal}
|
Retour
|
||||||
variant="contained"
|
|
||||||
color="secondary"
|
|
||||||
sx={{
|
|
||||||
textTransform: "none",
|
|
||||||
fontWeight: "bold",
|
|
||||||
backgroundColor: "#f44336",
|
|
||||||
"&:hover": { backgroundColor: "#d32f2f" },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Quitter
|
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Modal>
|
</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>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Section Action */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
backgroundColor: "#0e467f",
|
|
||||||
color: "white",
|
|
||||||
textAlign: "center",
|
|
||||||
padding: "40px 20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="h2"
|
|
||||||
sx={{
|
|
||||||
fontWeight: "bold",
|
|
||||||
mb: 2,
|
|
||||||
fontSize: { xs: '2rem', md: '3rem', lg: '3rem' }, // Responsive
|
|
||||||
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Prêt à démarrer ?
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Typography variant="body1" sx={{ mb: 4 }}>
|
|
||||||
Rejoignez-nous dès aujourd’hui et profitez de nos services pour
|
|
||||||
booster votre activité.
|
|
||||||
</Typography>
|
|
||||||
<Button
|
|
||||||
href={ctaLink}
|
|
||||||
variant="contained"
|
|
||||||
color="secondary"
|
|
||||||
size="large"
|
|
||||||
sx={{
|
|
||||||
textTransform: "none",
|
|
||||||
fontWeight: "bold",
|
|
||||||
backgroundColor: "#00bcd4",
|
|
||||||
"&:hover": { backgroundColor: "#0288d1" },
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{ctaText}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</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;
|
export default ServicePageTemplate;
|
||||||
@@ -49,7 +49,7 @@ function YourApp() {
|
|||||||
{/* Routes pour les services */}
|
{/* Routes pour les services */}
|
||||||
<Route path="/services/prestation-maitrise-oeuvre" element={<ServiceUn />} />
|
<Route path="/services/prestation-maitrise-oeuvre" element={<ServiceUn />} />
|
||||||
<Route path="/services/structure-beton-charpente-metallique-bois" element={<ServiceDeux />} />
|
<Route path="/services/structure-beton-charpente-metallique-bois" element={<ServiceDeux />} />
|
||||||
<Route path="/services/formation-video" element={<ServiceTrois />} />
|
<Route path="/services/electricite" element={<ServiceTrois />} />
|
||||||
<Route path="/admin/create-post" element={<CreatePost />} />
|
<Route path="/admin/create-post" element={<CreatePost />} />
|
||||||
<Route path="/post/:slug" element={<PostDetails />} />
|
<Route path="/post/:slug" element={<PostDetails />} />
|
||||||
<Route path="/admin/posts" element={<PostList />} />
|
<Route path="/admin/posts" element={<PostList />} />
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ export async function uploadImage(file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchPosts() {
|
||||||
|
const response = await fetch("https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/posts");
|
||||||
|
if (!response.ok) throw new Error("Erreur lors de la récupération des articles");
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 🔹 Crée un post WordPress avec une image mise en avant
|
* 🔹 Crée un post WordPress avec une image mise en avant
|
||||||
* @param {string} title - Le titre du post
|
* @param {string} title - Le titre du post
|
||||||
|
|||||||
Reference in New Issue
Block a user