mise a jour structure visuel BO
This commit is contained in:
@@ -1,18 +1,118 @@
|
||||
// ✅ Importations nécessaires
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
Box, Typography, Button, Table, TableBody, TableCell,
|
||||
TableContainer, TableHead, TableRow, Paper, TextField, Avatar
|
||||
Box,
|
||||
Typography,
|
||||
Button,
|
||||
Grid,
|
||||
Card,
|
||||
CardContent,
|
||||
CardMedia,
|
||||
TextField,
|
||||
Stack,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { Add, ArrowBack, Edit, Delete } from "@mui/icons-material";
|
||||
import api from "../../api";
|
||||
import { getToken } from "../../auth";
|
||||
import { deletePost } from "../../wordpress";
|
||||
import "../../assets/styleCours.css";
|
||||
|
||||
const BUTTON_BASE_SX = Object.freeze({
|
||||
borderRadius: 999,
|
||||
textTransform: "none",
|
||||
fontWeight: 600,
|
||||
letterSpacing: 0.3,
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
gap: 0.75,
|
||||
transition:
|
||||
"transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease",
|
||||
"&:hover": {
|
||||
transform: "translateY(-1px)",
|
||||
},
|
||||
"&:active": {
|
||||
transform: "translateY(0)",
|
||||
},
|
||||
});
|
||||
|
||||
const BUTTON_SIZE_SX = Object.freeze({
|
||||
small: {
|
||||
px: 2.1,
|
||||
py: 0.55,
|
||||
fontSize: "0.78rem",
|
||||
minHeight: 30,
|
||||
},
|
||||
medium: {
|
||||
px: 2.8,
|
||||
py: 0.8,
|
||||
fontSize: "0.86rem",
|
||||
minHeight: 36,
|
||||
},
|
||||
large: {
|
||||
px: 3.4,
|
||||
py: 1,
|
||||
fontSize: "0.94rem",
|
||||
minHeight: 42,
|
||||
},
|
||||
});
|
||||
|
||||
const BUTTON_VARIANT_SX = Object.freeze({
|
||||
primary: {
|
||||
background: "linear-gradient(135deg, #315397, #7bc0ff)",
|
||||
color: "#ffffff",
|
||||
border: "1px solid rgba(255,255,255,0.35)",
|
||||
boxShadow: "0 18px 28px -18px rgba(11, 26, 61, 0.55)",
|
||||
"&:hover": {
|
||||
background: "linear-gradient(135deg, #26467d, #6fb6ff)",
|
||||
boxShadow: "0 22px 32px -18px rgba(11, 26, 61, 0.6)",
|
||||
},
|
||||
},
|
||||
outline: {
|
||||
background: "rgba(255,255,255,0.84)",
|
||||
color: "#315397",
|
||||
border: "1px solid rgba(49,83,151,0.26)",
|
||||
"&:hover": {
|
||||
background: "rgba(255,255,255,0.96)",
|
||||
borderColor: "rgba(49,83,151,0.46)",
|
||||
boxShadow: "0 14px 22px -18px rgba(11, 26, 61, 0.4)",
|
||||
},
|
||||
},
|
||||
ghost: {
|
||||
background: "rgba(255,255,255,0.16)",
|
||||
color: "rgba(255,255,255,0.92)",
|
||||
border: "1px solid rgba(255,255,255,0.28)",
|
||||
backdropFilter: "blur(8px)",
|
||||
"&:hover": {
|
||||
background: "rgba(255,255,255,0.24)",
|
||||
boxShadow: "0 18px 28px -18px rgba(6, 18, 38, 0.45)",
|
||||
},
|
||||
},
|
||||
danger: {
|
||||
background: "linear-gradient(135deg, #f05b6b, #ff8a80)",
|
||||
color: "#3a0a0f",
|
||||
border: "1px solid rgba(240,91,107,0.35)",
|
||||
boxShadow: "0 18px 26px -18px rgba(105, 21, 33, 0.45)",
|
||||
"&:hover": {
|
||||
background: "linear-gradient(135deg, #e34659, #ff7575)",
|
||||
boxShadow: "0 22px 30px -18px rgba(105, 21, 33, 0.52)",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const composeButtonSx = (variant, size = "medium") => ({
|
||||
...BUTTON_BASE_SX,
|
||||
...(BUTTON_SIZE_SX[size] || BUTTON_SIZE_SX.medium),
|
||||
...(BUTTON_VARIANT_SX[variant] || BUTTON_VARIANT_SX.primary),
|
||||
});
|
||||
|
||||
const GestionArticles = () => {
|
||||
const [posts, setPosts] = useState([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// ✅ Vérifier si l'utilisateur est connecté
|
||||
@@ -26,7 +126,10 @@ const GestionArticles = () => {
|
||||
useEffect(() => {
|
||||
const fetchPosts = async () => {
|
||||
try {
|
||||
const response = await api.get("wp/v2/posts?_fields=id,title,excerpt,featured_media");
|
||||
setLoading(true);
|
||||
const response = await api.get(
|
||||
"wp/v2/posts?_fields=id,title,excerpt,featured_media,date,status"
|
||||
);
|
||||
const postsData = response.data;
|
||||
|
||||
const postsWithImages = await Promise.all(
|
||||
@@ -47,6 +150,8 @@ const GestionArticles = () => {
|
||||
setPosts(postsWithImages);
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur chargement des articles :", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -54,112 +159,408 @@ const GestionArticles = () => {
|
||||
}, []);
|
||||
|
||||
// ✅ Supprimer un article et son image associée
|
||||
const handleDeletePost = async (postId, imageId) => {
|
||||
if (window.confirm("Es-tu sûr de vouloir supprimer cet article ?")) {
|
||||
try {
|
||||
await deletePost(postId, imageId); // ✅ Appel de la fonction deletePost
|
||||
setPosts(posts.filter((post) => post.id !== postId)); // ✅ Met à jour la liste après suppression
|
||||
alert("✅ Article supprimé avec succès !");
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur suppression article :", error);
|
||||
alert("⚠ Erreur : impossible de supprimer l'article.");
|
||||
}
|
||||
}
|
||||
};
|
||||
const stripHtml = (value = "") =>
|
||||
value.replace(/(<([^>]+)>)/gi, "").replace(/ /gi, " ").trim();
|
||||
|
||||
// ✅ Filtrage des articles
|
||||
const filteredPosts = posts.filter((post) =>
|
||||
post.title.rendered.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
post.excerpt.rendered.replace(/(<([^>]+)>)/gi, "").replace(/ /g, " ").toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
const previewExcerpt = (value = "", limit = 160) => {
|
||||
const clean = stripHtml(value);
|
||||
return clean.length > limit ? `${clean.slice(0, limit)}…` : clean;
|
||||
};
|
||||
|
||||
const formatDate = (value) => {
|
||||
if (!value) {
|
||||
return "Date inconnue";
|
||||
}
|
||||
try {
|
||||
return new Intl.DateTimeFormat("fr-FR", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
}).format(new Date(value));
|
||||
} catch {
|
||||
return "Date inconnue";
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeletePost = async (postId, imageId) => {
|
||||
const confirmed = window.confirm(
|
||||
"Supprimer cet article et son visuel associé ?"
|
||||
);
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await deletePost(postId, imageId);
|
||||
setPosts((prev) => prev.filter((post) => post.id !== postId));
|
||||
alert("✅ Article supprimé avec succès !");
|
||||
} catch (error) {
|
||||
console.error("❌ Erreur suppression article :", error);
|
||||
alert("⚠ Erreur : impossible de supprimer l'article.");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = () => navigate("/admin/create-post");
|
||||
const handleBack = () => navigate("/admin/dashboard");
|
||||
const handleEdit = (postId) => navigate(`/admin/edit-post/${postId}`);
|
||||
|
||||
const filteredPosts = useMemo(() => {
|
||||
const term = searchTerm.trim().toLowerCase();
|
||||
if (!term) {
|
||||
return posts;
|
||||
}
|
||||
return posts.filter((post) => {
|
||||
const title = post.title?.rendered?.toLowerCase?.() || "";
|
||||
const excerpt = stripHtml(post.excerpt?.rendered || "").toLowerCase();
|
||||
return title.includes(term) || excerpt.includes(term);
|
||||
});
|
||||
}, [posts, searchTerm]);
|
||||
|
||||
const stats = useMemo(() => {
|
||||
const total = posts.length;
|
||||
const withImage = posts.reduce(
|
||||
(acc, post) => (post.image ? acc + 1 : acc),
|
||||
0
|
||||
);
|
||||
const latest = posts.reduce((current, candidate) => {
|
||||
if (!candidate?.date) {
|
||||
return current;
|
||||
}
|
||||
if (!current) {
|
||||
return candidate;
|
||||
}
|
||||
return new Date(candidate.date) > new Date(current.date)
|
||||
? candidate
|
||||
: current;
|
||||
}, null);
|
||||
return {
|
||||
total,
|
||||
withImage,
|
||||
withoutImage: total - withImage,
|
||||
latestLabel: latest?.title?.rendered || "Aucun article",
|
||||
latestDate: latest?.date ? formatDate(latest.date) : "—",
|
||||
};
|
||||
}, [posts]);
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "40px 20px" }}>
|
||||
{/* ✅ En-tête avec retour et création */}
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 4, mt:5 }}>
|
||||
<Button startIcon={<ArrowBack />} variant="outlined" color="secondary" onClick={() => navigate("/admin/dashboard")}>
|
||||
Retour au Dashboard
|
||||
</Button>
|
||||
<Typography variant="h4" sx={{ fontWeight: "bold", textAlign: "center", flexGrow: 1 }}>
|
||||
Gestion des Articles
|
||||
</Typography>
|
||||
<Button startIcon={<Add />} variant="contained" color="primary" onClick={() => navigate("/admin/create-post")}>
|
||||
Créer un article
|
||||
</Button>
|
||||
<Box
|
||||
className="glass-dashboard"
|
||||
sx={{
|
||||
minHeight: "100vh",
|
||||
position: "relative",
|
||||
px: { xs: 2, md: 6 },
|
||||
pt: { xs: 6, md: 8 },
|
||||
pb: { xs: 8, md: 10 },
|
||||
}}
|
||||
>
|
||||
<Box className="glass-orb orb-1" />
|
||||
<Box className="glass-orb orb-2" />
|
||||
<Box className="glass-orb orb-3" />
|
||||
|
||||
<Box sx={{ position: "relative", zIndex: 1, maxWidth: 1240, mx: "auto" }}>
|
||||
<Stack
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
justifyContent="space-between"
|
||||
alignItems={{ xs: "flex-start", md: "center" }}
|
||||
spacing={2}
|
||||
sx={{ mb: 3 }}
|
||||
>
|
||||
<Button
|
||||
startIcon={<ArrowBack />}
|
||||
variant="contained"
|
||||
onClick={handleBack}
|
||||
sx={{ ...composeButtonSx("ghost") }}
|
||||
>
|
||||
Retour
|
||||
</Button>
|
||||
<Stack spacing={0.5}>
|
||||
<Typography
|
||||
variant="overline"
|
||||
sx={{
|
||||
letterSpacing: 2,
|
||||
fontWeight: 700,
|
||||
color: "rgba(255,255,255,0.8)",
|
||||
}}
|
||||
>
|
||||
Contenu éditorial
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
color: "#ffffff",
|
||||
fontWeight: 800,
|
||||
letterSpacing: "-0.5px",
|
||||
}}
|
||||
>
|
||||
Gestion des articles
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
color: "rgba(255,255,255,0.85)",
|
||||
maxWidth: 520,
|
||||
}}
|
||||
>
|
||||
Consultez les publications WordPress, ajustez vos contenus et
|
||||
maintenez un flux éditorial cohérent pour Octopus.
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Button
|
||||
startIcon={<Add />}
|
||||
variant="contained"
|
||||
onClick={handleCreate}
|
||||
sx={{ ...composeButtonSx("primary") }}
|
||||
>
|
||||
Nouvel article
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Grid container spacing={2.5} sx={{ mb: 4 }}>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Card className="glass-subcard" sx={{ borderRadius: 3, p: 2.5 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.6)", fontWeight: 600 }}
|
||||
>
|
||||
Total articles
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ color: "#0b1a3d", fontWeight: 800, letterSpacing: "-0.5px" }}
|
||||
>
|
||||
{stats.total}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.65)", mt: 0.5 }}
|
||||
>
|
||||
{filteredPosts.length} résultat(s) après filtre
|
||||
</Typography>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Card className="glass-subcard" sx={{ borderRadius: 3, p: 2.5 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.6)", fontWeight: 600 }}
|
||||
>
|
||||
Articles illustrés
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ color: "#0b1a3d", fontWeight: 800, letterSpacing: "-0.5px" }}
|
||||
>
|
||||
{stats.withImage}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.65)", mt: 0.5 }}
|
||||
>
|
||||
{stats.withoutImage} sans visuel associé
|
||||
</Typography>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Card className="glass-subcard" sx={{ borderRadius: 3, p: 2.5 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.6)", fontWeight: 600 }}
|
||||
>
|
||||
Dernière publication
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{ color: "#0b1a3d", fontWeight: 700, lineHeight: 1.4 }}
|
||||
>
|
||||
{stats.latestLabel}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.65)", mt: 0.5 }}
|
||||
>
|
||||
{stats.latestDate}
|
||||
</Typography>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Card
|
||||
className="glass-subcard"
|
||||
sx={{
|
||||
borderRadius: 4,
|
||||
p: { xs: 2.5, md: 3 },
|
||||
mb: 4,
|
||||
boxShadow: "0 24px 36px -28px rgba(12, 29, 74, 0.45)",
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction={{ xs: "column", md: "row" }}
|
||||
spacing={2}
|
||||
alignItems={{ xs: "stretch", md: "center" }}
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Box>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ color: "#0b1a3d", fontWeight: 700 }}
|
||||
>
|
||||
Rechercher un article
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.65)" }}
|
||||
>
|
||||
Filtrez par titre ou résumé pour retrouver un contenu en quelques
|
||||
secondes.
|
||||
</Typography>
|
||||
</Box>
|
||||
<TextField
|
||||
label="Rechercher un article..."
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={searchTerm}
|
||||
onChange={(event) => setSearchTerm(event.target.value)}
|
||||
sx={{
|
||||
maxWidth: 380,
|
||||
"& .MuiOutlinedInput-root": {
|
||||
borderRadius: 999,
|
||||
backgroundColor: "rgba(255,255,255,0.92)",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
{loading ? (
|
||||
<Box sx={{ textAlign: "center", py: 6 }}>
|
||||
<CircularProgress color="inherit" />
|
||||
</Box>
|
||||
) : filteredPosts.length === 0 ? (
|
||||
<Card
|
||||
className="glass-subcard"
|
||||
sx={{
|
||||
borderRadius: 4,
|
||||
p: 4,
|
||||
textAlign: "center",
|
||||
color: "#0b1a3d",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, mb: 1 }}>
|
||||
Aucun article trouvé
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: "rgba(11, 26, 61, 0.65)" }}>
|
||||
Ajustez votre recherche ou créez un nouvel article pour alimenter le blog.
|
||||
</Typography>
|
||||
<Button
|
||||
startIcon={<Add />}
|
||||
variant="contained"
|
||||
onClick={handleCreate}
|
||||
sx={{ ...composeButtonSx("primary"), mt: 3 }}
|
||||
>
|
||||
Créer un article
|
||||
</Button>
|
||||
</Card>
|
||||
) : (
|
||||
<Grid container spacing={2.5}>
|
||||
{filteredPosts.map((post) => (
|
||||
<Grid item xs={12} md={6} key={post.id}>
|
||||
<Card
|
||||
className="glass-article-card"
|
||||
sx={{
|
||||
borderRadius: 4,
|
||||
overflow: "hidden",
|
||||
position: "relative",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
height: "100%",
|
||||
boxShadow: "0 32px 40px -28px rgba(12, 29, 74, 0.5)",
|
||||
}}
|
||||
>
|
||||
<CardMedia
|
||||
component="div"
|
||||
image={
|
||||
post.image ||
|
||||
"https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?auto=format&fit=crop&w=1200&q=80"
|
||||
}
|
||||
sx={{
|
||||
height: 200,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
/>
|
||||
<CardContent
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 1.5,
|
||||
p: { xs: 3, md: 3.5 },
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<Chip
|
||||
size="small"
|
||||
label={`ID ${post.id}`}
|
||||
sx={{
|
||||
bgcolor: "rgba(49,83,151,0.12)",
|
||||
color: "#315397",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
/>
|
||||
<Tooltip title={stats.latestLabel === post.title.rendered ? "Dernière publication" : ""}>
|
||||
<Chip
|
||||
size="small"
|
||||
label={formatDate(post.date)}
|
||||
sx={{
|
||||
bgcolor: "rgba(255,255,255,0.72)",
|
||||
color: "#0b1a3d",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ color: "#0b1a3d", fontWeight: 700, lineHeight: 1.4 }}
|
||||
>
|
||||
{post.title.rendered}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ color: "rgba(11, 26, 61, 0.68)", lineHeight: 1.6 }}
|
||||
>
|
||||
{previewExcerpt(post.excerpt?.rendered)}
|
||||
</Typography>
|
||||
<Stack
|
||||
direction={{ xs: "column", sm: "row" }}
|
||||
spacing={1}
|
||||
sx={{ mt: "auto" }}
|
||||
>
|
||||
<Button
|
||||
startIcon={<Edit />}
|
||||
variant="contained"
|
||||
onClick={() => handleEdit(post.id)}
|
||||
sx={{ ...composeButtonSx("outline", "small") }}
|
||||
>
|
||||
Modifier
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<Delete />}
|
||||
variant="contained"
|
||||
onClick={() => handleDeletePost(post.id, post.imageId)}
|
||||
sx={{ ...composeButtonSx("danger", "small") }}
|
||||
>
|
||||
Supprimer
|
||||
</Button>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* ✅ Recherche */}
|
||||
<TextField
|
||||
label="Rechercher un article..."
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
sx={{ mb: 3 }}
|
||||
/>
|
||||
|
||||
{/* ✅ Tableau des articles */}
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead sx={{ backgroundColor: "#0e467f" }}>
|
||||
<TableRow>
|
||||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>Image</TableCell>
|
||||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>Titre</TableCell>
|
||||
<TableCell sx={{ color: "white", fontWeight: "bold" }}>Résumé</TableCell>
|
||||
<TableCell sx={{ color: "white", fontWeight: "bold", textAlign: "center" }}>Actions</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{filteredPosts.length > 0 ? (
|
||||
filteredPosts.map((post) => (
|
||||
<TableRow key={post.id}>
|
||||
{/* ✅ Image en vedette */}
|
||||
<TableCell>
|
||||
<Avatar
|
||||
src={post.image || "https://via.placeholder.com/100"}
|
||||
variant="rounded"
|
||||
sx={{ width: 80, height: 80 }}
|
||||
/>
|
||||
</TableCell>
|
||||
{/* ✅ Titre de l'article */}
|
||||
<TableCell sx={{ fontWeight: "bold" }}>{post.title.rendered}</TableCell>
|
||||
{/* ✅ Résumé avec 100 caractères max */}
|
||||
<TableCell>
|
||||
{post.excerpt.rendered.replace(/(<([^>]+)>)/gi, "").replace(/ /g, " ").substring(0, 100)}...
|
||||
</TableCell>
|
||||
{/* ✅ Boutons Modifier et Supprimer */}
|
||||
<TableCell sx={{ textAlign: "center" }}>
|
||||
<Button startIcon={<Edit />}
|
||||
variant="outlined"
|
||||
color="warning"
|
||||
sx={{ mr: 1 }}
|
||||
onClick={() => navigate(`/admin/edit-post/${post.id}`)}
|
||||
>
|
||||
Modifier
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<Delete />}
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => handleDeletePost(post.id, post.imageId)}
|
||||
>
|
||||
Supprimer
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} sx={{ textAlign: "center", py: 2 }}>
|
||||
Aucun article trouvé.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default GestionArticles;
|
||||
export default GestionArticles;
|
||||
|
||||
Reference in New Issue
Block a user