gestion accueil MAJ avec gestion photo hero
This commit is contained in:
@@ -1,168 +1,224 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { updateHomePageACF, uploadImage } from "../../wordpress";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Box, Button, TextField, Typography, Snackbar, Alert, Paper, Card, CardMedia } from "@mui/material";
|
||||
import api from "../../api";
|
||||
|
||||
const PAGE_ID = 13; // ID de la page d'accueil
|
||||
import { updateHomePageACF, uploadImage } from "../../wordpress";
|
||||
import { getToken } from "../../auth";
|
||||
import {
|
||||
Typography,
|
||||
TextField,
|
||||
Button,
|
||||
Container,
|
||||
Paper,
|
||||
Box,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
|
||||
const GestionPageAccueil = () => {
|
||||
const [heroTitle, setHeroTitle] = useState("");
|
||||
const [heroText, setHeroText] = useState("");
|
||||
const [heroImage, setHeroImage] = useState(null);
|
||||
const [heroImageId, setHeroImageId] = useState(null);
|
||||
const [message, setMessage] = useState({ type: "", text: "" });
|
||||
const navigate = useNavigate(); // 🔥 Gestion de la navigation
|
||||
const navigate = useNavigate();
|
||||
const [heroTitle, setHeroTitle] = useState("");
|
||||
const [heroText, setHeroText] = useState("");
|
||||
const [heroImage, setHeroImage] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const [successMessage, setSuccessMessage] = useState("");
|
||||
|
||||
// ✅ Charger les données ACF existantes
|
||||
useEffect(() => {
|
||||
const fetchPageData = async () => {
|
||||
try {
|
||||
const response = await api.get(`wp/v2/pages/${PAGE_ID}?_fields=acf`);
|
||||
const acfData = response.data.acf;
|
||||
|
||||
if (acfData) {
|
||||
setHeroTitle(acfData.hero_title || "");
|
||||
setHeroText(acfData.hero_text || "");
|
||||
// ✅ Vérification de l'authentification (Redirection si non connecté)
|
||||
useEffect(() => {
|
||||
if (!getToken()) {
|
||||
navigate("/admin/login");
|
||||
}
|
||||
}, [navigate]);
|
||||
|
||||
if (acfData.img_hero) {
|
||||
setHeroImageId(acfData.img_hero);
|
||||
const imageResponse = await api.get(`wp/v2/media/${acfData.img_hero}`);
|
||||
setHeroImage(imageResponse.data.source_url);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur chargement ACF :", error);
|
||||
setMessage({ type: "error", text: "Erreur lors du chargement des données." });
|
||||
}
|
||||
};
|
||||
fetchPageData();
|
||||
}, []);
|
||||
// ✅ Chargement des données ACF depuis WordPress
|
||||
useEffect(() => {
|
||||
const fetchPageData = async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
"https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/pages/13?_fields=acf",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// ✅ Sauvegarde des données ACF
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const formData = {
|
||||
acf: {
|
||||
hero_title: heroTitle,
|
||||
hero_text: heroText,
|
||||
img_hero: heroImageId || null, // ✅ Mise à jour avec l'ID de l'image
|
||||
}
|
||||
};
|
||||
|
||||
console.log("📢 Envoi des nouvelles données ACF :", formData);
|
||||
await updateHomePageACF(PAGE_ID, formData);
|
||||
|
||||
setMessage({ type: "success", text: "✅ Mise à jour réussie !" });
|
||||
|
||||
// ✅ 🔥 Redirection vers le Dashboard après 1.5 sec
|
||||
setTimeout(() => {
|
||||
navigate("/admin/dashboard");
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur mise à jour ACF :", error);
|
||||
setMessage({ type: "error", text: "❌ Échec de la mise à jour. Vérifie les permissions WordPress." });
|
||||
if (!response.ok) {
|
||||
throw new Error("Erreur de chargement des données");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setHeroTitle(data.acf?.hero_title || "");
|
||||
setHeroText(data.acf?.hero_text || "");
|
||||
|
||||
// ✅ Récupération de l'image Hero
|
||||
if (data.acf?.img_hero) {
|
||||
const mediaResponse = await fetch(
|
||||
`https://preprod.octopusdesign.fr/api-octopus/server/wp-json/wp/v2/media/${data.acf.img_hero}`
|
||||
);
|
||||
const mediaData = await mediaResponse.json();
|
||||
setHeroImage(mediaData.source_url);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur chargement ACF :", error);
|
||||
setError("Impossible de charger les données.");
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ Gestion de l'upload d'image
|
||||
const handleImageUpload = async (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
fetchPageData();
|
||||
}, []);
|
||||
|
||||
try {
|
||||
const imageId = await uploadImage(file);
|
||||
setHeroImageId(imageId);
|
||||
// ✅ Mise à jour des champs ACF
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const newData = {
|
||||
hero_title: heroTitle,
|
||||
hero_text: heroText,
|
||||
};
|
||||
|
||||
const imageResponse = await api.get(`wp/v2/media/${imageId}`);
|
||||
setHeroImage(imageResponse.data.source_url);
|
||||
console.log("📢 Données envoyées pour mise à jour ACF :", newData);
|
||||
await updateHomePageACF(13, newData);
|
||||
|
||||
setMessage({ type: "success", text: "✅ Image uploadée avec succès !" });
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur lors de l'upload de l'image :", error);
|
||||
setMessage({ type: "error", text: "❌ Échec de l'upload de l'image." });
|
||||
}
|
||||
};
|
||||
setSuccessMessage("✅ Modifications enregistrées avec succès !");
|
||||
setTimeout(() => setSuccessMessage(""), 3000);
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur mise à jour :", error);
|
||||
setError("⚠ Impossible de mettre à jour les champs ACF.");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "40px", maxWidth: "700px", margin: "auto", mt: 5 }}>
|
||||
<Paper sx={{ padding: "30px", borderRadius: "10px", boxShadow: 3 }}>
|
||||
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
||||
🏠 Gestion de la Page d'Accueil
|
||||
// ✅ Gérer le téléversement d’une nouvelle image Hero
|
||||
const handleImageUpload = async (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
try {
|
||||
const imageId = await uploadImage(file);
|
||||
setHeroImage(URL.createObjectURL(file)); // Affichage immédiat
|
||||
await updateHomePageACF(13, { img_hero: imageId });
|
||||
setSuccessMessage("✅ Image mise à jour !");
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur lors de l'upload :", error);
|
||||
setError("❌ Échec de l'upload de l'image.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Container maxWidth="md" sx={{ mt: 16, mb:5 }}>
|
||||
<Paper elevation={6} sx={{ padding: 4, borderRadius: 3, backgroundColor: "#f8f9fa" }}>
|
||||
{/* ✅ En-tête */}
|
||||
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3, color: "#0e467f" }}>
|
||||
🏠 Gestion de la Page d'Accueil
|
||||
</Typography>
|
||||
|
||||
{/* ✅ Affichage du statut de chargement */}
|
||||
{loading ? (
|
||||
<Box display="flex" justifyContent="center" alignItems="center">
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
) : error ? (
|
||||
<Typography textAlign="center" color="error">
|
||||
{error}
|
||||
</Typography>
|
||||
) : (
|
||||
<>
|
||||
{/* ✅ Message de succès */}
|
||||
{successMessage && (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#d4edda",
|
||||
color: "#155724",
|
||||
padding: "12px",
|
||||
borderRadius: "8px",
|
||||
marginBottom: "16px",
|
||||
textAlign: "center",
|
||||
boxShadow: "0px 2px 10px rgba(0,0,0,0.1)",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1" fontWeight="bold">
|
||||
{successMessage}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{message.text && (
|
||||
<Snackbar open autoHideDuration={3000} onClose={() => setMessage({ type: "", text: "" })}>
|
||||
<Alert severity={message.type} sx={{ width: '100%' }}>
|
||||
{message.text}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
)}
|
||||
|
||||
{/* ✅ Aperçu de l'image actuelle */}
|
||||
{heroImage && (
|
||||
<Card sx={{ mb: 3, boxShadow: 3 }}>
|
||||
<CardMedia
|
||||
component="img"
|
||||
height="200"
|
||||
image={heroImage}
|
||||
alt="Image actuelle du héros"
|
||||
sx={{ objectFit: "cover" }}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* ✅ Bouton pour modifier l'image */}
|
||||
<Button variant="outlined" component="label" fullWidth sx={{ mb: 3 }}>
|
||||
Modifier l'image
|
||||
<input type="file" hidden onChange={handleImageUpload} />
|
||||
</Button>
|
||||
|
||||
<TextField
|
||||
label="Titre Héros"
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
value={heroTitle}
|
||||
onChange={(e) => setHeroTitle(e.target.value)}
|
||||
sx={{ "& .MuiInputBase-input": { fontSize: "1.2rem" } }}
|
||||
{/* ✅ Affichage de l'image actuelle */}
|
||||
{heroImage && (
|
||||
<Box sx={{ textAlign: "center", mb: 2 }}>
|
||||
<img
|
||||
src={heroImage}
|
||||
alt="Hero"
|
||||
style={{
|
||||
width: "100%",
|
||||
maxHeight: "250px",
|
||||
objectFit: "cover",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
label="Texte Héros"
|
||||
fullWidth
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
value={heroText}
|
||||
onChange={(e) => setHeroText(e.target.value)}
|
||||
multiline
|
||||
rows={3}
|
||||
sx={{ "& .MuiInputBase-input": { fontSize: "1rem" } }}
|
||||
/>
|
||||
{/* ✅ Bouton pour changer l'image */}
|
||||
<Button variant="contained" component="label" fullWidth sx={{ mb: 2 }}>
|
||||
📸 Modifier l'Image Hero
|
||||
<input type="file" hidden onChange={handleImageUpload} />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
fullWidth
|
||||
sx={{ mt: 3, fontSize: "1.1rem", fontWeight: "bold" }}
|
||||
onClick={handleSave}
|
||||
>
|
||||
💾 Enregistrer les modifications
|
||||
</Button>
|
||||
{/* ✅ Formulaire de modification */}
|
||||
<TextField
|
||||
label="Titre Héros"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={heroTitle}
|
||||
onChange={(e) => setHeroTitle(e.target.value)}
|
||||
sx={{ mb: 2, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
/>
|
||||
|
||||
{/* ✅ Bouton retour Dashboard */}
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
fullWidth
|
||||
sx={{ mt: 2, fontSize: "1rem", fontWeight: "bold" }}
|
||||
onClick={() => navigate("/admin/dashboard")}
|
||||
>
|
||||
⬅ Retour au Dashboard
|
||||
</Button>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
<TextField
|
||||
label="Texte Héros"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={heroText}
|
||||
onChange={(e) => setHeroText(e.target.value)}
|
||||
sx={{ mb: 2, backgroundColor: "#fff", borderRadius: "5px" }}
|
||||
multiline
|
||||
rows={3}
|
||||
/>
|
||||
|
||||
{/* ✅ Bouton d'enregistrement */}
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
fullWidth
|
||||
sx={{
|
||||
mt: 3,
|
||||
fontSize: "1.1rem",
|
||||
fontWeight: "bold",
|
||||
color:"#ffffff",
|
||||
backgroundColor: "#0e467f",
|
||||
"&:hover": { backgroundColor: "#093a6b" },
|
||||
}}
|
||||
onClick={handleSave}
|
||||
>
|
||||
💾 Enregistrer les modifications
|
||||
</Button>
|
||||
|
||||
{/* ✅ Bouton retour au Dashboard */}
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
fullWidth
|
||||
sx={{ mt: 2, fontSize: "1rem", fontWeight: "bold", borderColor: "#0e467f", color: "#0e467f" }}
|
||||
onClick={() => navigate("/admin/dashboard")}
|
||||
>
|
||||
⬅ Retour au Dashboard
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default GestionPageAccueil;
|
||||
Reference in New Issue
Block a user