Gestion de page ACF maj

This commit is contained in:
sebvtl728
2025-02-11 00:38:29 +01:00
parent 038dd3498a
commit 7df66f13df
2 changed files with 138 additions and 238 deletions
+63 -188
View File
@@ -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,15 +122,13 @@ 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">
<Paper elevation={6} sx={{ padding: 4, borderRadius: 3, mt:10 }}> <Paper elevation={6} sx={{ padding: 4, borderRadius: 3, mt: 10 }}>
<Button <Button
startIcon={<ArrowBack />} startIcon={<ArrowBack />}
variant="outlined" variant="outlined"
@@ -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>
+36 -11
View File
@@ -1,40 +1,65 @@
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: [
{ {
title: "Titre", title: "Titre",
description: "Description.", description: "Description.",
modalText:"Description Modal.", modalText: "Description Modal.",
modalImage: "https://picsum.photos/id/300/800/400.webp", modalImage: "https://picsum.photos/id/300/800/400.webp",
}, },
{ {
title: "Titre", title: "Titre",
description: "Description.", description: "Description.",
modalText:"Description Modal.", modalText: "Description Modal.",
modalImage: "https://picsum.photos/id/301/800/400.webp", modalImage: "https://picsum.photos/id/301/800/400.webp",
}, },
{ {
title: "Titre", title: "Titre",
description: "Description.", description: "Description.",
modalText:"Description Modal.", modalText: "Description Modal.",
modalImage: "https://picsum.photos/id/302/800/400.webp", modalImage: "https://picsum.photos/id/302/800/400.webp",
}, },
], ],
@@ -56,4 +81,4 @@ const ServiceUn = () => {
return <ServicePageTemplate {...serviceDetails} />; return <ServicePageTemplate {...serviceDetails} />;
}; };
export default ServiceUn; export default ServiceQuatre;