améliorations de l'édition des romans
This commit is contained in:
parent
2584e75ba0
commit
e4f1880870
64
admin/api/delete-story.php
Normal file
64
admin/api/delete-story.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../includes/auth.php';
|
||||
require_once '../../includes/stories.php';
|
||||
|
||||
// Vérification de l'authentification
|
||||
if (!Auth::check()) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['success' => false, 'error' => 'Non autorisé']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Vérification de la méthode HTTP
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Méthode non autorisée']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Récupération et validation des données
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$storyId = $input['id'] ?? null;
|
||||
|
||||
if (!$storyId) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'ID du roman manquant']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
// Récupération du roman
|
||||
$story = Stories::get($storyId);
|
||||
if (!$story) {
|
||||
throw new Exception('Roman non trouvé');
|
||||
}
|
||||
|
||||
// Suppression de l'image de couverture si elle existe
|
||||
if (!empty($story['cover'])) {
|
||||
$coverPath = __DIR__ . '/../../' . $story['cover'];
|
||||
if (file_exists($coverPath)) {
|
||||
unlink($coverPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Suppression du fichier JSON du roman
|
||||
$storyFile = __DIR__ . '/../../stories/' . $storyId . '.json';
|
||||
if (file_exists($storyFile)) {
|
||||
unlink($storyFile);
|
||||
|
||||
// Réponse de succès
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Roman supprimé avec succès'
|
||||
]);
|
||||
} else {
|
||||
throw new Exception('Fichier du roman introuvable');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => 'Erreur lors de la suppression : ' . $e->getMessage()
|
||||
]);
|
||||
}
|
145
assets/js/admin.js
Normal file
145
assets/js/admin.js
Normal file
@ -0,0 +1,145 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Gestion de la suppression des romans
|
||||
const storyList = document.querySelector('.stories-list');
|
||||
if (storyList) {
|
||||
storyList.addEventListener('click', async (e) => {
|
||||
if (e.target.matches('.delete-story')) {
|
||||
const storyId = e.target.dataset.id;
|
||||
if (confirmDeletion(storyId)) {
|
||||
await deleteStory(storyId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Confirmation de suppression avec informations du roman
|
||||
function confirmDeletion(storyId) {
|
||||
const storyCard = document.querySelector(`[data-id="${storyId}"]`).closest('.story-item');
|
||||
const title = storyCard.querySelector('h2').textContent;
|
||||
return confirm(`Voulez-vous vraiment supprimer le roman "${title}" ? Cette action est irréversible.`);
|
||||
}
|
||||
|
||||
// Suppression d'un roman via l'API
|
||||
async function deleteStory(storyId) {
|
||||
try {
|
||||
const response = await fetch('api/delete-story.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ id: storyId })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
// Animation de suppression et retrait du DOM
|
||||
const storyCard = document.querySelector(`[data-id="${storyId}"]`).closest('.story-item');
|
||||
storyCard.style.opacity = '0';
|
||||
storyCard.style.transform = 'translateX(-100%)';
|
||||
setTimeout(() => {
|
||||
storyCard.remove();
|
||||
showNotification('Roman supprimé avec succès');
|
||||
}, 300);
|
||||
} else {
|
||||
throw new Error(result.error || 'Erreur lors de la suppression');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Erreur serveur');
|
||||
}
|
||||
} catch (error) {
|
||||
showNotification(error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Système de notification
|
||||
function showNotification(message, type = 'success') {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification ${type}`;
|
||||
notification.textContent = message;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Animation d'entrée
|
||||
setTimeout(() => {
|
||||
notification.style.opacity = '1';
|
||||
notification.style.transform = 'translateY(0)';
|
||||
}, 10);
|
||||
|
||||
// Auto-suppression après 3 secondes
|
||||
setTimeout(() => {
|
||||
notification.style.opacity = '0';
|
||||
notification.style.transform = 'translateY(-100%)';
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Gestion du formulaire de déconnexion
|
||||
const logoutForm = document.querySelector('.logout-form');
|
||||
if (logoutForm) {
|
||||
logoutForm.addEventListener('submit', (e) => {
|
||||
if (!confirm('Voulez-vous vraiment vous déconnecter ?')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Fonction utilitaire pour détecter les changements non sauvegardés
|
||||
let hasUnsavedChanges = false;
|
||||
|
||||
function detectUnsavedChanges() {
|
||||
const forms = document.querySelectorAll('form');
|
||||
forms.forEach(form => {
|
||||
const initialState = new FormData(form).toString();
|
||||
|
||||
form.addEventListener('change', () => {
|
||||
const currentState = new FormData(form).toString();
|
||||
hasUnsavedChanges = initialState !== currentState;
|
||||
});
|
||||
});
|
||||
|
||||
// Avertissement avant de quitter la page avec des changements non sauvegardés
|
||||
window.addEventListener('beforeunload', (e) => {
|
||||
if (hasUnsavedChanges) {
|
||||
e.preventDefault();
|
||||
e.returnValue = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Style des notifications
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.notification {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.notification.success {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.notification.error {
|
||||
background-color: #f44336;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.story-item {
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Initialisation des fonctionnalités
|
||||
detectUnsavedChanges();
|
||||
});
|
@ -3,6 +3,7 @@ class Stories {
|
||||
private static $storiesDir = __DIR__ . '/../stories/';
|
||||
|
||||
public static function getAll() {
|
||||
self::ensureDirectoryExists();
|
||||
$stories = [];
|
||||
foreach (glob(self::$storiesDir . '*.json') as $file) {
|
||||
$story = json_decode(file_get_contents($file), true);
|
||||
@ -12,6 +13,7 @@ class Stories {
|
||||
}
|
||||
|
||||
public static function get($id) {
|
||||
self::ensureDirectoryExists();
|
||||
$file = self::$storiesDir . $id . '.json';
|
||||
if (!file_exists($file)) {
|
||||
return null;
|
||||
@ -20,7 +22,40 @@ class Stories {
|
||||
}
|
||||
|
||||
public static function save($story) {
|
||||
self::ensureDirectoryExists();
|
||||
|
||||
// Vérifier que l'ID est valide
|
||||
if (empty($story['id'])) {
|
||||
throw new Exception('L\'ID du roman est requis');
|
||||
}
|
||||
|
||||
// Créer le chemin complet du fichier
|
||||
$file = self::$storiesDir . $story['id'] . '.json';
|
||||
return file_put_contents($file, json_encode($story, JSON_PRETTY_PRINT));
|
||||
|
||||
// Encoder en JSON avec options de formatage
|
||||
$jsonContent = json_encode($story, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
if ($jsonContent === false) {
|
||||
throw new Exception('Erreur lors de l\'encodage JSON: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
// Écrire le fichier
|
||||
$bytesWritten = file_put_contents($file, $jsonContent);
|
||||
if ($bytesWritten === false) {
|
||||
throw new Exception('Erreur lors de l\'écriture du fichier: ' . error_get_last()['message']);
|
||||
}
|
||||
|
||||
return $bytesWritten;
|
||||
}
|
||||
|
||||
private static function ensureDirectoryExists() {
|
||||
if (!file_exists(self::$storiesDir)) {
|
||||
if (!mkdir(self::$storiesDir, 0755, true)) {
|
||||
throw new Exception('Impossible de créer le dossier stories/');
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_writable(self::$storiesDir)) {
|
||||
throw new Exception('Le dossier stories/ n\'est pas accessible en écriture');
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user