Maj Api and create contact page

This commit is contained in:
sebvtl728
2025-01-03 13:10:09 +01:00
parent 8fcd728887
commit 037cffaa0a
7 changed files with 994 additions and 81 deletions
+462 -31
View File
@@ -1,40 +1,471 @@
import React, { useState, useEffect } from 'react';
import SEO from '../SEO';
import api from '../../api';
import React, { useState, useEffect } from "react";
import {
Box,
TextField,
Typography,
Button,
Grid,
Checkbox,
FormControlLabel,
Snackbar,
Alert,
CircularProgress,
Card,
CardContent,
Modal,
Fade,
Backdrop,
} from "@mui/material";
import SEO from "../SEO";
import api from "../../api";
const Contact = () => {
// États pour le SEO
const [metaTitle, setMetaTitle] = useState('Titre par défaut');
const [metaDescription, setMetaDescription] = useState('Description par défaut.');
const [metaTitle, setMetaTitle] = useState("Contactez-nous");
const [metaDescription, setMetaDescription] = useState(
"Contactez notre équipe pour plus d'informations."
);
const [formData, setFormData] = useState({
name: "",
email: "",
subject: "",
message: "",
consent: false,
});
const [errors, setErrors] = useState({});
const [loading, setLoading] = useState(false);
const [successMessage, setSuccessMessage] = useState(false);
const [openLightbox, setOpenLightbox] = useState(false);
useEffect(() => {
const fetchPageData = async () => {
try {
// Appel à l'API pour récupérer les données
const response = await api.get('wp/v2/pages/116?_fields=acf,rank_math_title,rank_math_description');
const { rank_math_title, rank_math_description } = response.data;
useEffect(() => {
const fetchSEOData = async () => {
try {
const response = await api.get(
"wp/v2/pages/116?_fields=acf,rank_math_title,rank_math_description"
);
const { rank_math_title, rank_math_description } = response.data;
setMetaTitle(rank_math_title || "Contactez-nous");
setMetaDescription(rank_math_description || "Contactez notre équipe.");
} catch (error) {
console.error("Erreur lors de la récupération des données SEO :", error);
}
};
// Mise à jour des métadonnées SEO
setMetaTitle(rank_math_title || 'Titre par défaut');
setMetaDescription(rank_math_description || 'Description par défaut.');
} catch (error) {
console.error('Erreur lors de la récupération des données :', error);
fetchSEOData();
}, []);
const validate = () => {
const newErrors = {};
if (!formData.name) newErrors.name = "Le nom est requis.";
if (!formData.email || !/\S+@\S+\.\S+/.test(formData.email))
newErrors.email = "Une adresse e-mail valide est requise.";
if (!formData.subject) newErrors.subject = "Le sujet est requis.";
if (!formData.message) newErrors.message = "Le message est requis.";
if (!formData.consent)
newErrors.consent = "Vous devez accepter la politique de confidentialité.";
return newErrors;
};
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === "checkbox" ? checked : value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
const validationErrors = validate();
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
setLoading(true);
try {
const response = await fetch(
"https://votre-site.com/wp-json/custom/v1/contact",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
}
);
if (response.ok) {
setSuccessMessage(true);
setFormData({
name: "",
email: "",
subject: "",
message: "",
consent: false,
});
} else {
const errorData = await response.json();
throw new Error(errorData.message || "Une erreur est survenue.");
}
} catch (error) {
alert(error.message);
} finally {
setLoading(false);
}
}
};
const handleOpenLightbox = () => {
setOpenLightbox(true);
};
const handleCloseLightbox = () => {
setOpenLightbox(false);
};
return (
<Box>
{/* SEO */}
<SEO title={metaTitle} description={metaDescription} />
{/* Section Attention */}
<Box
sx={{
backgroundImage: `url('https://via.placeholder.com/1920x800')`,
backgroundSize: "cover",
backgroundPosition: "center",
minHeight: "50vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
color: "white",
padding: "20px",
}}
>
<Box>
<Typography
variant="h2"
sx={{
fontWeight: "bold",
fontSize: { xs: "2rem", md: "3rem", lg: "4rem" },
mb: 2,
}}
>
Contactez-nous
</Typography>
<Typography
variant="h6"
sx={{
fontSize: { xs: "1rem", md: "1.5rem" },
maxWidth: "600px",
mx: "auto",
}}
>
Une question? Une demande particulière? Remplissez le formulaire
ci-dessous ou consultez nos coordonnées.
</Typography>
</Box>
</Box>
{/* Section Coordonnées et Horaires */}
<Box sx={{ padding: "40px 20px", backgroundColor: "#f9f9f9" }}>
<Grid container spacing={4}>
{/* Coordonnées */}
<Grid item xs={12} md={6}>
<Card
sx={{
boxShadow: 2,
borderRadius: 2,
padding: "20px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
height: "80%",
}}
>
<Box>
<Typography
variant="h4"
sx={{
fontWeight: "bold",
color: "#0e467f",
mb: 2,
}}
>
Nos coordonnées
</Typography>
<Typography variant="body1">
<strong>Adresse :</strong> 123 Rue Exemple, Paris, France
</Typography>
<Typography variant="body1">
<strong>Téléphone :</strong> +33 1 23 45 67 89
</Typography>
<Typography variant="body1">
<strong>Email :</strong> contact@exemple.com
</Typography>
</Box>
<Box
onClick={handleOpenLightbox}
sx={{
position: "relative",
cursor: "pointer",
width: "120px",
height: "120px",
borderRadius: "8px",
overflow: "hidden",
boxShadow: 3,
"&:hover": {
transform: "scale(1.10)",
boxShadow: 4,
transition: "transform 0.3s, box-shadow 0.3s",
},
"&:hover::before": {
content: '"Cliquez pour agrandir"',
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: "rgba(0, 0, 0, 0.7)",
color: "white",
padding: "5px 10px",
borderRadius: "4px",
fontSize: "12px",
},
}}
>
<img
src="https://picsum.photos/id/442/300.webp"
alt="Carte"
style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>
</Box>
</Card>
</Grid>
{/* Horaires */}
<Grid item xs={12} md={6}>
<Card
sx={{
boxShadow: 2,
borderRadius: 2,
padding: "20px",
backgroundColor: "#fff",
height: "80%",
}}
>
<CardContent>
<Typography
variant="h4"
sx={{
fontWeight: "bold",
color: "#0e467f",
mb: 2,
textAlign: "center",
}}
>
Horaires d'ouverture
</Typography>
<Typography variant="body1">
<strong>Lundi - Vendredi :</strong> 9h00 - 18h00
</Typography>
<Typography variant="body1">
<strong>Samedi :</strong> 10h00 - 14h00
</Typography>
<Typography variant="body1">
<strong>Dimanche :</strong> Fermé
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
</Box>
{/* Lightbox */}
<Modal
open={openLightbox}
onClose={handleCloseLightbox}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{ timeout: 500 }}
>
<Fade in={openLightbox}>
<Box
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "90%",
maxWidth: "800px",
backgroundColor: "white",
boxShadow: 24,
borderRadius: 2,
overflow: "hidden",
}}
>
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2624.9998319324044!2d2.2922928156738935!3d48.85884407928788!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47e66fdf78ccf6fd%3A0x10793db0b6d65f9b!2sEiffel+Tower!5e0!3m2!1sen!2sfr!4v1618237600000!5m2!1sen!2sfr"
width="100%"
height="400"
title="Carte interactive"
style={{ border: 0 }}
allowFullScreen=""
loading="lazy"
/>
</Box>
</Fade>
</Modal>
{/* Section Action */}
<Box
sx={{
backgroundColor: "#0e467f",
color: "white",
textAlign: "center",
padding: "40px 20px",
}}
>
<Typography
variant="h4"
sx={{
fontWeight: "bold",
mb: 2,
fontSize: { xs: "1.5rem", md: "2rem" },
}}
>
Besoin d'une assistance immédiate?
</Typography>
<Button
href="/aide"
variant="contained"
sx={{
textTransform: "none",
fontWeight: "bold",
backgroundColor: "#00bcd4",
"&:hover": { backgroundColor: "#0288d1" },
}}
>
Obtenez de l'aide maintenant
</Button>
</Box>
{/* Formulaire de contact */}
<Box
sx={{
maxWidth: "800px",
margin: "auto",
padding: "40px",
boxShadow: 3,
borderRadius: 2,
backgroundColor: "#fff",
mt: 4,
}}
>
<Typography
variant="h4"
sx={{ mb: 4, textAlign: "center", fontWeight: "bold", color: "#0e467f" }}
>
Formulaire de contact
</Typography>
<form onSubmit={handleSubmit} noValidate>
<TextField
label="Nom"
name="name"
value={formData.name}
onChange={handleChange}
error={Boolean(errors.name)}
helperText={errors.name}
fullWidth
margin="normal"
variant="outlined"
/>
<TextField
label="E-mail"
name="email"
value={formData.email}
onChange={handleChange}
error={Boolean(errors.email)}
helperText={errors.email}
fullWidth
margin="normal"
variant="outlined"
/>
<TextField
label="Sujet"
name="subject"
value={formData.subject}
onChange={handleChange}
error={Boolean(errors.subject)}
helperText={errors.subject}
fullWidth
margin="normal"
variant="outlined"
/>
<TextField
label="Message"
name="message"
value={formData.message}
onChange={handleChange}
error={Boolean(errors.message)}
helperText={errors.message}
fullWidth
margin="normal"
variant="outlined"
multiline
rows={4}
/>
<FormControlLabel
control={
<Checkbox
name="consent"
checked={formData.consent}
onChange={handleChange}
/>
}
};
label="J'accepte la politique de confidentialité."
sx={{ mt: 2, color: errors.consent ? "red" : "inherit" }}
/>
{errors.consent && (
<Typography variant="caption" color="error">
{errors.consent}
</Typography>
)}
<Box sx={{ textAlign: "center", mt: 3 }}>
<Button
type="submit"
variant="contained"
color="primary"
size="large"
disabled={loading}
sx={{
textTransform: "none",
fontWeight: "bold",
px: 5,
}}
>
{loading ? (
<CircularProgress size={24} sx={{ color: "#fff" }} />
) : (
"Envoyer"
)}
</Button>
</Box>
</form>
fetchPageData();
}, []); // Exécution au premier rendu
return (
<div>
{/* SEO */}
<SEO title={metaTitle} description={metaDescription} />
{/* Contenu de la page */}
<h1>Contact</h1>
<p>Bienvenue sur la page Contact.</p>
</div>
);
<Snackbar
open={successMessage}
autoHideDuration={6000}
onClose={() => setSuccessMessage(false)}
>
<Alert onClose={() => setSuccessMessage(false)} severity="success">
Message envoyé avec succès!
</Alert>
</Snackbar>
</Box>
</Box>
);
};
export default Contact;