gestion accueil MAJ
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
|||||||
import LogoutIcon from "@mui/icons-material/Logout"; // Icône de déconnexion
|
import LogoutIcon from "@mui/icons-material/Logout"; // Icône de déconnexion
|
||||||
import ArticleIcon from "@mui/icons-material/Article";
|
import ArticleIcon from "@mui/icons-material/Article";
|
||||||
import DashboardIcon from "@mui/icons-material/Dashboard";
|
import DashboardIcon from "@mui/icons-material/Dashboard";
|
||||||
|
import HomeIcon from "@mui/icons-material/Home"; // Icône pour la gestion page d'accueil
|
||||||
|
|
||||||
function Dashboard() {
|
function Dashboard() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -51,10 +52,10 @@ function Dashboard() {
|
|||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
boxShadow: 6,
|
boxShadow: 6,
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
position: "relative", // Permet de positionner des éléments enfants
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Bouton de déconnexion placé en haut à gauche de la boîte blanche */}
|
{/* Bouton de déconnexion placé en haut à gauche */}
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="error"
|
color="error"
|
||||||
@@ -69,9 +70,7 @@ function Dashboard() {
|
|||||||
fontSize: "0.875rem",
|
fontSize: "0.875rem",
|
||||||
padding: "6px 12px",
|
padding: "6px 12px",
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* En-tête */}
|
{/* En-tête */}
|
||||||
<Typography variant="h4" sx={{ fontWeight: "bold", mb: 4, mt: 4 }}>
|
<Typography variant="h4" sx={{ fontWeight: "bold", mb: 4, mt: 4 }}>
|
||||||
@@ -81,7 +80,39 @@ function Dashboard() {
|
|||||||
|
|
||||||
{/* Cartes du Dashboard */}
|
{/* Cartes du Dashboard */}
|
||||||
<Grid container spacing={3} justifyContent="center">
|
<Grid container spacing={3} justifyContent="center">
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
{/* ✅ Gestion Page d'Accueil - Première carte */}
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<Card
|
||||||
|
onClick={() => navigate("/admin/Gestion-Page-Accueil")}
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
textAlign: "center",
|
||||||
|
padding: 2,
|
||||||
|
transition: "0.3s",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#0e467f",
|
||||||
|
color: "#ffffff",
|
||||||
|
transform: "scale(1.05)",
|
||||||
|
boxShadow: 8,
|
||||||
|
},
|
||||||
|
"&:hover svg": {
|
||||||
|
fill: "#ffffff",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardContent>
|
||||||
|
<IconButton sx={{ fontSize: 40, color: "#0e467f" }}>
|
||||||
|
<HomeIcon fontSize="inherit" />
|
||||||
|
</IconButton>
|
||||||
|
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
|
||||||
|
Gestion Page d'Accueil
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* ✅ Gérer les Articles - Deuxième carte */}
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
<Card
|
<Card
|
||||||
onClick={() => navigate("/admin/gestion-articles")}
|
onClick={() => navigate("/admin/gestion-articles")}
|
||||||
sx={{
|
sx={{
|
||||||
@@ -109,35 +140,6 @@ function Dashboard() {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card
|
|
||||||
onClick={() => navigate("/admin/Gestion-Page-Accueil")}
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
textAlign: "center",
|
|
||||||
padding: 2,
|
|
||||||
transition: "0.3s",
|
|
||||||
"&:hover": {
|
|
||||||
backgroundColor: "#0e467f",
|
|
||||||
color: "#ffffff",
|
|
||||||
transform: "scale(1.05)",
|
|
||||||
boxShadow: 8,
|
|
||||||
},
|
|
||||||
"&:hover svg": {
|
|
||||||
fill: "#ffffff",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CardContent>
|
|
||||||
<IconButton sx={{ fontSize: 40, color: "#0e467f" }}>
|
|
||||||
<ArticleIcon fontSize="inherit" />
|
|
||||||
</IconButton>
|
|
||||||
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
|
|
||||||
Gestion Page d'Accueil
|
|
||||||
</Typography>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,145 +1,168 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { updateHomePageACF, uploadImage } from "../../wordpress";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { updateHomePageACF } from "../../wordpress";
|
import { Box, Button, TextField, Typography, Snackbar, Alert, Paper, Card, CardMedia } from "@mui/material";
|
||||||
import { getToken } from "../../auth";
|
import api from "../../api";
|
||||||
import {
|
|
||||||
Box,
|
const PAGE_ID = 13; // ID de la page d'accueil
|
||||||
Typography,
|
|
||||||
TextField,
|
|
||||||
Button,
|
|
||||||
Container,
|
|
||||||
Paper,
|
|
||||||
} from "@mui/material";
|
|
||||||
|
|
||||||
const GestionPageAccueil = () => {
|
const GestionPageAccueil = () => {
|
||||||
const navigate = useNavigate();
|
const [heroTitle, setHeroTitle] = useState("");
|
||||||
const [heroTitle, setHeroTitle] = useState("");
|
const [heroText, setHeroText] = useState("");
|
||||||
const [heroText, setHeroText] = useState("");
|
const [heroImage, setHeroImage] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [heroImageId, setHeroImageId] = useState(null);
|
||||||
const [error, setError] = useState(null);
|
const [message, setMessage] = useState({ type: "", text: "" });
|
||||||
|
const navigate = useNavigate(); // 🔥 Gestion de la navigation
|
||||||
|
|
||||||
// ✅ Vérification de l'authentification (Redirection si non connecté)
|
// ✅ Charger les données ACF existantes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!getToken()) {
|
const fetchPageData = async () => {
|
||||||
navigate("/admin/login");
|
try {
|
||||||
}
|
const response = await api.get(`wp/v2/pages/${PAGE_ID}?_fields=acf`);
|
||||||
}, [navigate]);
|
const acfData = response.data.acf;
|
||||||
|
|
||||||
// ✅ Chargement des données ACF depuis WordPress
|
if (acfData) {
|
||||||
useEffect(() => {
|
setHeroTitle(acfData.hero_title || "");
|
||||||
const fetchPageData = async () => {
|
setHeroText(acfData.hero_text || "");
|
||||||
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",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (acfData.img_hero) {
|
||||||
throw new Error("Erreur de chargement des données");
|
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();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ✅ 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." });
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
setHeroTitle(data.acf?.hero_title || "");
|
|
||||||
setHeroText(data.acf?.hero_text || "");
|
|
||||||
setLoading(false);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("❌ Erreur chargement ACF :", error);
|
|
||||||
setError("Impossible de charger les données.");
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPageData();
|
// ✅ Gestion de l'upload d'image
|
||||||
}, []);
|
const handleImageUpload = async (event) => {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
// ✅ Mise à jour des champs ACF
|
try {
|
||||||
const handleSave = async () => {
|
const imageId = await uploadImage(file);
|
||||||
try {
|
setHeroImageId(imageId);
|
||||||
const newData = {
|
|
||||||
hero_title: heroTitle,
|
|
||||||
hero_text: heroText,
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log("📢 Données envoyées pour mise à jour ACF :", newData);
|
const imageResponse = await api.get(`wp/v2/media/${imageId}`);
|
||||||
const updatedData = await updateHomePageACF(13, newData);
|
setHeroImage(imageResponse.data.source_url);
|
||||||
|
|
||||||
alert("✅ Mise à jour réussie !");
|
setMessage({ type: "success", text: "✅ Image uploadée avec succès !" });
|
||||||
console.log("🔍 Données mises à jour reçues :", updatedData);
|
} catch (error) {
|
||||||
|
console.error("❌ Erreur lors de l'upload de l'image :", error);
|
||||||
|
setMessage({ type: "error", text: "❌ Échec de l'upload de l'image." });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window.location.reload(); // 🔄 Rafraîchissement pour voir les changements
|
return (
|
||||||
} catch (error) {
|
<Box sx={{ padding: "40px", maxWidth: "700px", margin: "auto", mt: 5 }}>
|
||||||
console.error("❌ Erreur mise à jour :", error);
|
<Paper sx={{ padding: "30px", borderRadius: "10px", boxShadow: 3 }}>
|
||||||
alert("⚠ Impossible de mettre à jour les champs ACF.");
|
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
||||||
}
|
🏠 Gestion de la Page d'Accueil
|
||||||
};
|
</Typography>
|
||||||
|
|
||||||
return (
|
{message.text && (
|
||||||
<Container maxWidth="md" sx={{ mt: 5 }}>
|
<Snackbar open autoHideDuration={3000} onClose={() => setMessage({ type: "", text: "" })}>
|
||||||
<Paper elevation={3} sx={{ padding: 4, borderRadius: 3 }}>
|
<Alert severity={message.type} sx={{ width: '100%' }}>
|
||||||
{/* ✅ En-tête */}
|
{message.text}
|
||||||
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", mb: 3 }}>
|
</Alert>
|
||||||
Gestion de la Page d'Accueil
|
</Snackbar>
|
||||||
</Typography>
|
)}
|
||||||
|
|
||||||
{/* ✅ Affichage du statut de chargement */}
|
{/* ✅ Aperçu de l'image actuelle */}
|
||||||
{loading ? (
|
{heroImage && (
|
||||||
<Typography textAlign="center">Chargement des données...</Typography>
|
<Card sx={{ mb: 3, boxShadow: 3 }}>
|
||||||
) : error ? (
|
<CardMedia
|
||||||
<Typography textAlign="center" color="error">
|
component="img"
|
||||||
{error}
|
height="200"
|
||||||
</Typography>
|
image={heroImage}
|
||||||
) : (
|
alt="Image actuelle du héros"
|
||||||
<>
|
sx={{ objectFit: "cover" }}
|
||||||
{/* ✅ Formulaire de modification */}
|
/>
|
||||||
<TextField
|
</Card>
|
||||||
label="Titre Héros"
|
)}
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={heroTitle}
|
|
||||||
onChange={(e) => setHeroTitle(e.target.value)}
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextField
|
{/* ✅ Bouton pour modifier l'image */}
|
||||||
label="Texte Héros"
|
<Button variant="outlined" component="label" fullWidth sx={{ mb: 3 }}>
|
||||||
fullWidth
|
Modifier l'image
|
||||||
variant="outlined"
|
<input type="file" hidden onChange={handleImageUpload} />
|
||||||
value={heroText}
|
</Button>
|
||||||
onChange={(e) => setHeroText(e.target.value)}
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* ✅ Bouton d'enregistrement */}
|
<TextField
|
||||||
<Button
|
label="Titre Héros"
|
||||||
variant="contained"
|
fullWidth
|
||||||
color="primary"
|
margin="normal"
|
||||||
fullWidth
|
variant="outlined"
|
||||||
sx={{ mt: 3 }}
|
value={heroTitle}
|
||||||
onClick={handleSave}
|
onChange={(e) => setHeroTitle(e.target.value)}
|
||||||
>
|
sx={{ "& .MuiInputBase-input": { fontSize: "1.2rem" } }}
|
||||||
Enregistrer les modifications
|
/>
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* ✅ Bouton retour au Dashboard */}
|
<TextField
|
||||||
<Button
|
label="Texte Héros"
|
||||||
variant="outlined"
|
fullWidth
|
||||||
color="secondary"
|
margin="normal"
|
||||||
fullWidth
|
variant="outlined"
|
||||||
sx={{ mt: 2 }}
|
value={heroText}
|
||||||
onClick={() => navigate("/admin/dashboard")}
|
onChange={(e) => setHeroText(e.target.value)}
|
||||||
>
|
multiline
|
||||||
Retour au Dashboard
|
rows={3}
|
||||||
</Button>
|
sx={{ "& .MuiInputBase-input": { fontSize: "1rem" } }}
|
||||||
</>
|
/>
|
||||||
)}
|
|
||||||
</Paper>
|
<Button
|
||||||
</Container>
|
variant="contained"
|
||||||
);
|
color="primary"
|
||||||
|
fullWidth
|
||||||
|
sx={{ mt: 3, fontSize: "1.1rem", fontWeight: "bold" }}
|
||||||
|
onClick={handleSave}
|
||||||
|
>
|
||||||
|
💾 Enregistrer les modifications
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{/* ✅ 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>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GestionPageAccueil;
|
export default GestionPageAccueil;
|
||||||
@@ -278,10 +278,13 @@ add_action('rest_api_init', function () {
|
|||||||
'acf', // Champ ACF
|
'acf', // Champ ACF
|
||||||
[
|
[
|
||||||
'get_callback' => function ($object) {
|
'get_callback' => function ($object) {
|
||||||
return get_fields($object['id']);
|
return get_fields($object['id']); // ✅ Vérifie que l'ID est correct
|
||||||
},
|
},
|
||||||
'update_callback' => function ($value, $object) {
|
'update_callback' => function ($value, $object) {
|
||||||
return update_fields($object->ID, $value);
|
foreach ($value as $field_key => $field_value) {
|
||||||
|
update_field($field_key, $field_value, $object->ID); // ✅ Correction ici
|
||||||
|
}
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
'schema' => null,
|
'schema' => null,
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user