Gestion de page ACF maj
This commit is contained in:
@@ -20,13 +20,6 @@ function EditPageACF() {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [successMessage, setSuccessMessage] = useState("");
|
const [successMessage, setSuccessMessage] = useState("");
|
||||||
const deleteFAQItem = (index) => {
|
|
||||||
const updatedArray = acfFields.faq?.faq_list.filter((_, i) => i !== index);
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
faq: { ...acfFields.faq, faq_list: updatedArray },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// ✅ Vérifier l'authentification
|
// ✅ Vérifier l'authentification
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -35,7 +28,7 @@ function EditPageACF() {
|
|||||||
}
|
}
|
||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
// ✅ Récupérer les champs ACF des pages
|
// ✅ Récupérer les champs ACF de la page
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPage = async () => {
|
const fetchPage = async () => {
|
||||||
console.log("📢 Récupération de la page avec ID :", id);
|
console.log("📢 Récupération de la page avec ID :", id);
|
||||||
@@ -46,6 +39,7 @@ function EditPageACF() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const pageData = await getPageById(id);
|
const pageData = await getPageById(id);
|
||||||
|
|
||||||
if (!pageData || !pageData.acf) {
|
if (!pageData || !pageData.acf) {
|
||||||
@@ -54,14 +48,12 @@ function EditPageACF() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAcfFields({
|
setAcfFields(pageData.acf);
|
||||||
...pageData.acf,
|
|
||||||
faq_list: Array.isArray(pageData.acf?.faq?.faq_list)
|
|
||||||
? pageData.acf.faq.faq_list
|
|
||||||
: [], // ✅ On s'assure d'avoir un tableau vide si ce n'est pas défini
|
|
||||||
});
|
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
setError("⚠ Impossible de récupérer les champs ACF.");
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPage();
|
fetchPage();
|
||||||
@@ -71,13 +63,8 @@ function EditPageACF() {
|
|||||||
const handleUpdateACF = async (e) => {
|
const handleUpdateACF = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const updatedACF = {
|
|
||||||
...acfFields,
|
|
||||||
faq_list: Array.isArray(acfFields?.faq_list) ? acfFields.faq_list : [],
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updatePageACF(id, updatedACF);
|
await updatePageACF(id, acfFields);
|
||||||
setSuccessMessage("✅ Modifications enregistrées !");
|
setSuccessMessage("✅ Modifications enregistrées !");
|
||||||
setTimeout(() => navigate("/admin/pages-acf"), 2000);
|
setTimeout(() => navigate("/admin/pages-acf"), 2000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -86,7 +73,7 @@ function EditPageACF() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Gérer la modification des champs ACF (y compris objets et tableaux)
|
// ✅ Gérer la modification des champs ACF
|
||||||
const handleFieldChange = (field, value) => {
|
const handleFieldChange = (field, value) => {
|
||||||
setAcfFields((prevFields) => ({
|
setAcfFields((prevFields) => ({
|
||||||
...prevFields,
|
...prevFields,
|
||||||
@@ -94,25 +81,36 @@ function EditPageACF() {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Ajouter, modifier et supprimer des entrées de FAQ
|
// ✅ Gérer la FAQ : ajouter, modifier et supprimer des entrées
|
||||||
const handleFAQChange = (index, field, value) => {
|
const handleFAQChange = (index, field, value) => {
|
||||||
const updatedFAQ = [...acfFields.faq_list];
|
const updatedFAQ = [...(acfFields.faq?.faq_list || [])];
|
||||||
updatedFAQ[index][field] = value;
|
updatedFAQ[index][field] = value;
|
||||||
setAcfFields({ ...acfFields, faq_list: updatedFAQ });
|
setAcfFields({
|
||||||
|
...acfFields,
|
||||||
|
faq: { ...acfFields.faq, faq_list: updatedFAQ },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const addFAQ = () => {
|
const addFAQ = () => {
|
||||||
setAcfFields({
|
setAcfFields({
|
||||||
...acfFields,
|
...acfFields,
|
||||||
faq_list: [...acfFields.faq_list, { question: "", answer: "" }],
|
faq: {
|
||||||
|
...acfFields.faq,
|
||||||
|
faq_list: [...(acfFields.faq?.faq_list || []), { question: "", answer: "" }],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteFAQ = (index) => {
|
const deleteFAQ = (index) => {
|
||||||
setAcfFields({
|
const updatedFAQList = acfFields.faq.faq_list.filter((_, i) => i !== index);
|
||||||
...acfFields,
|
const updatedACF = { ...acfFields, faq: { ...acfFields.faq, faq_list: updatedFAQList } };
|
||||||
faq_list: acfFields.faq_list.filter((_, i) => i !== index),
|
|
||||||
});
|
// 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) return <Typography>Chargement...</Typography>;
|
if (loading) return <Typography>Chargement...</Typography>;
|
||||||
@@ -124,11 +122,9 @@ function EditPageACF() {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
backgroundImage:
|
backgroundImage: "url('https://source.unsplash.com/1600x900/?technology')",
|
||||||
"url('https://source.unsplash.com/1600x900/?technology')",
|
|
||||||
backgroundSize: "cover",
|
backgroundSize: "cover",
|
||||||
backgroundPosition: "center",
|
backgroundPosition: "center",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
@@ -143,42 +139,35 @@ function EditPageACF() {
|
|||||||
Retour à la gestion des pages
|
Retour à la gestion des pages
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Typography
|
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
||||||
variant="h4"
|
Modifier la Page
|
||||||
sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}
|
|
||||||
>
|
|
||||||
Modifier les Champs
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{error && (
|
{error && <Typography textAlign="center" color="error" sx={{ mb: 2 }}>{error}</Typography>}
|
||||||
<Typography textAlign="center" color="error" sx={{ mb: 2 }}>
|
{successMessage && <Typography sx={{ color: "green", textAlign: "center", mb: 2 }}>{successMessage}</Typography>}
|
||||||
{error}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
{successMessage && (
|
|
||||||
<Typography sx={{ color: "green", textAlign: "center", mb: 2 }}>
|
|
||||||
{successMessage}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<form onSubmit={handleUpdateACF}>
|
<form onSubmit={handleUpdateACF}>
|
||||||
{/* ✅ Affichage dynamique des champs ACF */}
|
{/* ✅ Affichage dynamique des champs ACF sauf la FAQ */}
|
||||||
{Object.keys(acfFields).map((field) => {
|
<Paper>
|
||||||
const value = acfFields[field];
|
{Object.keys(acfFields)
|
||||||
|
.filter((field) => field !== "faq" && field !== "faq_list") // 🔥 On exclut la FAQ et faq_list
|
||||||
// ✅ Si c'est un objet (comme `faq`), afficher ses sous-champs
|
.map((field) => (
|
||||||
if (field === "faq") {
|
<TextField
|
||||||
return null; // ✅ On ne veut pas afficher `faq` en tant que champ texte
|
key={field}
|
||||||
}
|
label={field.replace(/_/g, " ")}
|
||||||
if (field === "faq_list" && Array.isArray(value)) {
|
fullWidth
|
||||||
const faqData = acfFields.faq?.faq_list || [];
|
variant="outlined"
|
||||||
|
value={acfFields[field] || ""}
|
||||||
return (
|
onChange={(e) => handleFieldChange(field, e.target.value)}
|
||||||
<Box key="faq_list" sx={{ mb: 3 }}>
|
sx={{ mb: 2, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold", mb: 1 }}>
|
/>
|
||||||
FAQ
|
))}
|
||||||
</Typography>
|
</Paper>
|
||||||
{faqData.map((item, index) => (
|
{/* ✅ 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>
|
||||||
|
{acfFields.faq.faq_list.map((item, index) => (
|
||||||
<Box
|
<Box
|
||||||
key={index}
|
key={index}
|
||||||
sx={{
|
sx={{
|
||||||
@@ -186,7 +175,7 @@ function EditPageACF() {
|
|||||||
padding: 2,
|
padding: 2,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
mb: 2,
|
mb: 2,
|
||||||
position: "relative", // Permet d'aligner le bouton en haut à droite
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -194,14 +183,7 @@ function EditPageACF() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={item.question || ""}
|
value={item.question || ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => handleFAQChange(index, "question", e.target.value)}
|
||||||
const updatedArray = [...faqData];
|
|
||||||
updatedArray[index].question = e.target.value;
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
faq: { ...acfFields.faq, faq_list: updatedArray },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -211,135 +193,28 @@ function EditPageACF() {
|
|||||||
multiline
|
multiline
|
||||||
rows={3}
|
rows={3}
|
||||||
value={item.answer || ""}
|
value={item.answer || ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => handleFAQChange(index, "answer", e.target.value)}
|
||||||
const updatedArray = [...faqData];
|
|
||||||
updatedArray[index].answer = e.target.value;
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
faq: { ...acfFields.faq, faq_list: updatedArray },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
sx={{ mb: 1, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<Delete />}
|
startIcon={<Delete />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="error"
|
color="error"
|
||||||
onClick={() => deleteFAQItem(index)}
|
onClick={() => deleteFAQ(index)}
|
||||||
sx={{
|
sx={{ position: "absolute", top: 10, right: 10 }}
|
||||||
position: "absolute",
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Supprimer
|
Supprimer
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
<Button
|
<Button startIcon={<Add />} variant="contained" color="primary" onClick={addFAQ} sx={{ mb: 2 }}>
|
||||||
startIcon={<Add />}
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
faq: {
|
|
||||||
...acfFields.faq,
|
|
||||||
faq_list: [...faqData, { question: "", answer: "" }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
>
|
|
||||||
Ajouter une question
|
Ajouter une question
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
)}
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ Si c'est un tableau (comme `faq_list`), afficher chaque élément
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return (
|
|
||||||
<Box key={field} sx={{ mb: 3 }}>
|
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold", mb: 1 }}>
|
|
||||||
{field.replace(/_/g, " ")}
|
|
||||||
</Typography>
|
|
||||||
{value.map((item, index) => (
|
|
||||||
<Box
|
|
||||||
key={index}
|
|
||||||
sx={{
|
|
||||||
border: "1px solid #ccc",
|
|
||||||
padding: 2,
|
|
||||||
borderRadius: 2,
|
|
||||||
mb: 2,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{Object.keys(item).map((subField) => (
|
|
||||||
<TextField
|
|
||||||
key={subField}
|
|
||||||
label={subField.replace(/_/g, " ")}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={item[subField] || ""}
|
|
||||||
onChange={(e) => {
|
|
||||||
const updatedArray = [...value];
|
|
||||||
updatedArray[index][subField] = e.target.value;
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
[field]: updatedArray,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
mb: 1,
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
borderRadius: "5px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
startIcon={<Add />}
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setAcfFields({
|
|
||||||
...acfFields,
|
|
||||||
[field]: [...value, {}], // ✅ Ajoute un objet vide
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
>
|
|
||||||
Ajouter une entrée
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ Gérer les champs simples
|
<Button type="submit" variant="contained" color="primary" fullWidth startIcon={<Save />} sx={{ mt: 3 }}>
|
||||||
return (
|
|
||||||
<TextField
|
|
||||||
key={field}
|
|
||||||
label={field.replace(/_/g, " ")}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={value || ""}
|
|
||||||
onChange={(e) =>
|
|
||||||
setAcfFields({ ...acfFields, [field]: e.target.value })
|
|
||||||
}
|
|
||||||
sx={{ mb: 2, backgroundColor: "#fff", borderRadius: "5px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
fullWidth
|
|
||||||
startIcon={<Save />}
|
|
||||||
sx={{ mt: 3 }}
|
|
||||||
>
|
|
||||||
Enregistrer les modifications
|
Enregistrer les modifications
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,22 +1,47 @@
|
|||||||
import React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import ServicePageTemplate from "../ServicePageTemplate";
|
import ServicePageTemplate from "../ServicePageTemplate";
|
||||||
|
import { getPageById } from "../../wordpress";
|
||||||
|
|
||||||
|
const ServiceQuatre = () => {
|
||||||
|
const [acfData, setAcfData] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const pageId = 590; // 🔥 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 ServiceUn = () => {
|
|
||||||
const serviceDetails = {
|
const serviceDetails = {
|
||||||
// Hero
|
// Hero
|
||||||
title: 'Titre héros', // ✅ Modifiable individuellement
|
title: acfData?.title || "Titre héros !", // ✅ Modifiable individuellement
|
||||||
subtitle: 'Description, héros', // ✅ Modifiable individuellement
|
subtitle: acfData?.sub_title || "Description, héros", // ✅ Modifiable individuellement
|
||||||
|
|
||||||
image: "https://picsum.photos/id/1021/1920/1080.webp",
|
image: "https://picsum.photos/id/1021/1920/1080.webp",
|
||||||
ctaText: "En savoir plus",
|
ctaText: "En savoir plus",
|
||||||
ctaLink: "/contact",
|
ctaLink: "/contact",
|
||||||
|
|
||||||
// section 1
|
// section 1
|
||||||
interestTitle: 'Titre interet', // ✅ Modifiable individuellement
|
interestTitle: acfData?.interest_Title || "Titre interet", // ✅ Modifiable individuellement
|
||||||
description: 'Description interet', // ✅ Modifiable individuellement
|
description: "Description interet", // ✅ Modifiable individuellement
|
||||||
|
|
||||||
// section 2
|
// section 2
|
||||||
desirTitle: 'Titre', // ✅ Modifiable individuellement
|
desirTitle: "Titre", // ✅ Modifiable individuellement
|
||||||
|
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
@@ -56,4 +81,4 @@ const ServiceUn = () => {
|
|||||||
return <ServicePageTemplate {...serviceDetails} />;
|
return <ServicePageTemplate {...serviceDetails} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ServiceUn;
|
export default ServiceQuatre;
|
||||||
|
|||||||
Reference in New Issue
Block a user