+
+
AVANT
-
![]()
+
-
+
APRÈS
-
![]()
+
@@ -68,3 +61,4 @@
+
diff --git a/prestations/js/ajouter_avant_apres.js b/prestations/js/ajouter_avant_apres.js
index 440e9a7..4d184f2 100644
--- a/prestations/js/ajouter_avant_apres.js
+++ b/prestations/js/ajouter_avant_apres.js
@@ -30,13 +30,48 @@ const afterPreview = document.getElementById("afterPreview");
const successMsg = document.getElementById("successMsg");
const errorMsg = document.getElementById("errorMsg");
+const errorFormat = document.getElementById("errorFormat");
+
+// Formats autorisés
+const allowedTypes = ["image/jpeg", "image/png", "image/webp"];
// ===============================
-// Prévisualisation images
+// Fonctions utilitaires
+// ===============================
+function hideMessages() {
+ successMsg.classList.add("d-none");
+ errorMsg.classList.add("d-none");
+ errorFormat.classList.add("d-none");
+}
+
+function isValidFormat(file) {
+ if (!file) return false;
+ return allowedTypes.includes(file.type);
+}
+
+// ===============================
+// Prévisualisation image AVANT
+// + contrôle du format
// ===============================
beforeInput.addEventListener("change", function () {
+ hideMessages();
+
const file = this.files[0];
- if (!file) return;
+
+ if (!file) {
+ beforePreview.style.display = "none";
+ beforePreview.src = "#";
+ return;
+ }
+
+ // Vérif format
+ if (!isValidFormat(file)) {
+ errorFormat.classList.remove("d-none");
+ this.value = ""; // reset le champ
+ beforePreview.style.display = "none";
+ beforePreview.src = "#";
+ return;
+ }
const reader = new FileReader();
reader.onload = e => {
@@ -46,9 +81,29 @@ beforeInput.addEventListener("change", function () {
reader.readAsDataURL(file);
});
+// ===============================
+// Prévisualisation image APRÈS
+// + contrôle du format
+// ===============================
afterInput.addEventListener("change", function () {
+ hideMessages();
+
const file = this.files[0];
- if (!file) return;
+
+ if (!file) {
+ afterPreview.style.display = "none";
+ afterPreview.src = "#";
+ return;
+ }
+
+ // Vérif format
+ if (!isValidFormat(file)) {
+ errorFormat.classList.remove("d-none");
+ this.value = ""; // reset le champ
+ afterPreview.style.display = "none";
+ afterPreview.src = "#";
+ return;
+ }
const reader = new FileReader();
reader.onload = e => {
@@ -64,23 +119,35 @@ afterInput.addEventListener("change", function () {
form.addEventListener("submit", function (e) {
e.preventDefault();
- // Reset messages
- errorMsg.classList.add("d-none");
- successMsg.classList.add("d-none");
+ hideMessages();
- // Validation simple
- if (!titleInput.value.trim() || !typeInput.value.trim() || !beforeInput.files[0] || !afterInput.files[0]) {
+ // Champs obligatoires
+ if (
+ !titleInput.value.trim() ||
+ !typeInput.value.trim() ||
+ !beforeInput.files[0] ||
+ !afterInput.files[0]
+ ) {
errorMsg.classList.remove("d-none");
return;
}
+ const beforeFile = beforeInput.files[0];
+ const afterFile = afterInput.files[0];
+
+ // Vérification format des deux images
+ if (!isValidFormat(beforeFile) || !isValidFormat(afterFile)) {
+ errorFormat.classList.remove("d-none");
+ return;
+ }
+
// Nouvelle entrée (simulation)
const newPair = {
id: galleryPairs.length + 1,
titre: titleInput.value.trim(),
type: typeInput.value.trim(),
- avant: URL.createObjectURL(beforeInput.files[0]),
- apres: URL.createObjectURL(afterInput.files[0])
+ avant: URL.createObjectURL(beforeFile),
+ apres: URL.createObjectURL(afterFile)
};
galleryPairs.push(newPair);
diff --git a/prestations/js/liste_avant_apres.js b/prestations/js/liste_avant_apres.js
index 64c5fc9..b1eaaec 100644
--- a/prestations/js/liste_avant_apres.js
+++ b/prestations/js/liste_avant_apres.js
@@ -22,6 +22,14 @@ let galleryPairs = [
const tableBody = document.getElementById("prestationTableBody");
const succesDeleteMsg = document.getElementById("succesDeleteMsg");
+// Modal & bouton de confirmation
+const deleteModalEl = document.getElementById("deleteModal");
+const confirmDeleteBtn = document.getElementById("confirmDeleteBtn");
+const deleteModal = new bootstrap.Modal(deleteModalEl);
+
+// ID de la paire en attente de suppression
+let pairIdToDelete = null;
+
// ===============================
// Fonction d'affichage
// ===============================
@@ -36,27 +44,33 @@ function displayPairs() {
${pair.type} |
-
+
|
-
+
|
-
+ |
+
-
- Voir
+
+
+ Voir
+
-
- Modifier
+
+
+ Modifier
+
-
-
+
+
+
|
`;
@@ -65,26 +79,39 @@ function displayPairs() {
}
// ===============================
-// Fonction de suppression
+// Ouvrir le modal de suppression
+// ===============================
+function openDeleteModal(id) {
+ pairIdToDelete = id; // on mémorise l'id
+ deleteModal.show(); // on ouvre le modal
+}
+
+// ===============================
+// Fonction de suppression réelle
// ===============================
function deletePair(id) {
- if (!confirm("Voulez-vous vraiment supprimer cette paire ?")) {
- return;
- }
-
galleryPairs = galleryPairs.filter(pair => pair.id !== id);
displayPairs();
succesDeleteMsg.classList.remove("d-none");
- // Disparaît après 2 secondes
setTimeout(() => {
succesDeleteMsg.classList.add("d-none");
}, 2000);
}
+// ===============================
+// Clic sur "Supprimer" dans le modal
+// ===============================
+confirmDeleteBtn.addEventListener("click", () => {
+ if (pairIdToDelete !== null) {
+ deletePair(pairIdToDelete);
+ pairIdToDelete = null;
+ }
+ deleteModal.hide();
+});
+
// ===============================
// Chargement initial
// ===============================
displayPairs();
-
diff --git a/prestations/js/modifier_avant_apres.js b/prestations/js/modifier_avant_apres.js
index fae9bde..5111af8 100644
--- a/prestations/js/modifier_avant_apres.js
+++ b/prestations/js/modifier_avant_apres.js
@@ -19,6 +19,11 @@ const galleryPairs = [
}
];
+// ===============================
+// Formats d'images autorisés
+// ===============================
+const allowedTypes = ["image/jpeg", "image/png", "image/webp"];
+
// Sélecteurs
const editForm = document.getElementById("editPairForm");
const pairIdInput = document.getElementById("pairId");
@@ -31,6 +36,7 @@ const afterPreview = document.getElementById("afterPreview");
const successMsg = document.getElementById("successMsg");
const errorMsg = document.getElementById("errorMsg");
+const errorFormat = document.getElementById("errorFormat");
// ===============================
// Récup ID dans l'URL
@@ -71,23 +77,39 @@ function loadPairData() {
afterPreview.src = pair.apres;
}
-// Prévisu des nouvelles images
-beforeInput.addEventListener("change", function () {
- const file = this.files[0];
+// ===============================
+// Gestion du changement d'image
+// ===============================
+function handleImageChange(inputEl, previewEl) {
+ const file = inputEl.files[0];
if (!file) return;
+ // Vérification format
+ if (!allowedTypes.includes(file.type)) {
+ // Format non autorisé
+ errorFormat.classList.remove("d-none");
+ inputEl.value = ""; // reset du champ
+ previewEl.src = ""; // reset de la prévisu
+ return;
+ }
+
+ // Format OK → on cache le message d'erreur
+ errorFormat.classList.add("d-none");
+
const reader = new FileReader();
- reader.onload = e => beforePreview.src = e.target.result;
+ reader.onload = e => {
+ previewEl.src = e.target.result;
+ };
reader.readAsDataURL(file);
+}
+
+// Prévisu des nouvelles images + contrôle format
+beforeInput.addEventListener("change", function () {
+ handleImageChange(beforeInput, beforePreview);
});
afterInput.addEventListener("change", function () {
- const file = this.files[0];
- if (!file) return;
-
- const reader = new FileReader();
- reader.onload = e => afterPreview.src = e.target.result;
- reader.readAsDataURL(file);
+ handleImageChange(afterInput, afterPreview);
});
// Soumission
@@ -96,6 +118,7 @@ editForm.addEventListener("submit", function (e) {
errorMsg.classList.add("d-none");
successMsg.classList.add("d-none");
+ errorFormat.classList.add("d-none");
if (!titleInput.value.trim()) {
errorMsg.textContent = "Le titre est obligatoire.";
@@ -103,7 +126,16 @@ editForm.addEventListener("submit", function (e) {
return;
}
- // Ici ce serait un fetch vers l'API en vrai.
+ // Double check format côté submit (au cas où)
+ const filesToCheck = [beforeInput.files[0], afterInput.files[0]];
+ for (const file of filesToCheck) {
+ if (!file || !allowedTypes.includes(file.type)) {
+ errorFormat.classList.remove("d-none");
+ return;
+ }
+ }
+
+
successMsg.classList.remove("d-none");
setTimeout(() => {