From 9fb079c9a7d253d7e4858d4e1dbbceab9e276d34 Mon Sep 17 00:00:00 2001 From: fatima Date: Wed, 7 Oct 2026 09:42:34 +0000 Subject: [PATCH] Ajout de la suppression de la reservation de salle --- .../static/gestion_salle/js/index.js | 162 +++++++++--------- .../templates/gestion_salle/index.html | 2 +- .../parts/modalDetailResevation.html | 15 +- gestion_salle/urls.py | 5 + gestion_salle/views.py | 63 ++++++- 5 files changed, 155 insertions(+), 92 deletions(-) diff --git a/gestion_salle/static/gestion_salle/js/index.js b/gestion_salle/static/gestion_salle/js/index.js index 7770404..f676e62 100644 --- a/gestion_salle/static/gestion_salle/js/index.js +++ b/gestion_salle/static/gestion_salle/js/index.js @@ -2,7 +2,71 @@ const $ = (element) => document.getElementById(element); const { Schedule } = calendarjs; let dateAUtiliser = new Date().toISOString().split('T')[0]; -let currentReservationId = null; + +function afficherDetailsReservation(data) { + const reservationId = data.id_reservation || data.id; + $("id_reservation_detail").value = reservationId; + $("id_reservation_refus").value = reservationId; + $("id_reservation_zoom").value = reservationId; + $("employe").value = data.employe; + $("salle").value = data.salle; + $("statut-reservation").textContent = data.statut; + $("date_evenement").value = data.date_evenement || data.date_debut; + $("heure_debut").value = data.heure_debut; + $("heure_fin").value = data.heure_fin; + $("motif_reservation").value = data.motif_reservation; + $("besoin_zoom").checked = data.besoin_zoom; + $("besoin_ordinateur").checked = data.besoin_ordinateur ?? data.besoin_ordi; + $("lien_zoom").value = data.lien_zoom || ""; + $("lien_zoom_container").classList.toggle("d-none", !data.besoin_zoom); + + const currentUserId = $("current-user-id").dataset.userId; + const isOwner = data.est_proprietaire === true + || String(data.employe_id) === currentUserId; + const isPending = data.est_en_attente === true + || data.statut === "En attente" + || data.statut === "en_attente"; + + $("bouton-supprimer-reservation").classList.toggle( + "d-none", + !(isOwner && isPending) + ); + + for (const id of ["refuserReservation", "refuserReservationInfo", "bouton-valider", "bouton-valider-info"]) { + const button = $(id); + if (button) { + button.style.display = isPending && !isOwner ? "inline-block" : "none"; + } + } +} + +function supprimerReservation(reservationId) { + if (!window.confirm("Voulez-vous vraiment supprimer cette demande de réservation en attente ?")) { + return; + } + + const form = $("formulaire-details"); + const csrf = form.querySelector("[name=csrfmiddlewaretoken]").value; + const url = $("bouton-supprimer-reservation").dataset.url.replace( + "/0/", + `/${reservationId}/` + ); + + fetch(url, { + method: "POST", + headers: {"X-CSRFToken": csrf}, + }) + .then(response => response.json().then(data => ({response, data}))) + .then(({response, data}) => { + window.alert(data.message); + if (response.ok && data.success) { + window.location.reload(); + } + }) + .catch(() => { + window.alert("La suppression a échoué. Veuillez réessayer."); + }); +} const calendrier = Schedule(document.getElementById('planning-reservation'), { type: 'weekdays', @@ -19,31 +83,7 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), { return response.json(); }) .then(data => { - currentReservationId = data.id_reservation; - $("id_reservation_detail").value = data.id_reservation; - $("id_reservation_refus").value = data.id_reservation; - $("id_reservation_zoom").value = data.id_reservation; - $("employe").value=data.employe; - $("salle").value=data.salle; - $("statut-reservation").innerHTML=data.statut; - $("date_evenement").value=data.date_evenement; - $("heure_debut").value=data.heure_debut; - $("heure_fin").value=data.heure_fin; - $("motif_reservation").value=data.motif_reservation; - $("besoin_zoom").checked=data.besoin_zoom; - $("besoin_ordinateur").checked=data.besoin_ordinateur; - $("lien_zoom").value=data.lien_zoom; - - const zoomContainer = $("lien_zoom_container"); - if (!data.besoin_zoom) { - zoomContainer.classList.add("d-none"); - } else { - zoomContainer.classList.remove("d-none"); - } - if (data.besoin_zoom === false){ - $("lien_zoom_container").className = "d-none"; - } - + afficherDetailsReservation(data); }) .catch(error => console.error("Impossible de charger les détails de la réservation :", error)); } @@ -58,6 +98,10 @@ $('semaineDate').addEventListener('change', () => { calendrier.render(); }) +$("bouton-supprimer-reservation").addEventListener("click", () => { + supprimerReservation($("id_reservation_detail").value); +}); + evenement_defini = null $("liste-salle").addEventListener("change", (e) => { @@ -76,39 +120,22 @@ $("liste-salle").addEventListener("change", (e) => { function chargement_evenement(){ const url = $("planning-reservation").dataset.url; fetch (url) - .then(response => response.json()) + .then(response => { + if (!response.ok) { + throw new Error(`Erreur HTTP ${response.status}`); + } + return response.json(); + }) .then(data => { calendrier.setData(data); }) + .catch(error => console.error("Impossible de charger les réservations :", error)); } document.addEventListener("DOMContentLoaded", function () { chargement_evenement() }) -$("bouton-annuler").addEventListener("click", (e) => { - e.preventDefault(); - - const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value; - const url_annuler = $("formulaire-details").dataset.urlannuler; - - e.preventDefault(); - - fetch( - url_annuler, - { - method: "POST", - headers: { - "X-Requested-With": "XMTHttpRequest", - "X-CSRFToken": csrf - }, - body: new FormData($("formulaire-details")) - } - ) - .then(response => response.json()) - .then(data => console.log(data)) -}) - if($("bouton-valider")){ $("bouton-valider").addEventListener("click", (e) => { const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value; @@ -180,40 +207,7 @@ const tableau_reservation_attente = new Tabulator("#tableau-reservation-attente" tableau_reservation_attente.on("rowClick", (row, rowData) => { const data = rowData.getData(); - console.log(data); - - if(data.besoin_zoom === false){ - $("lien_zoom_container").className = 'd-none'; - } - - const id_user = $("current-user-id").dataset.userId; - - $("id_reservation_detail").value = data.id; - $("id_reservation_refus").value = data.id; - $("id_reservation_zoom").value = data.id; - - $("employe").value=data.employe; - $("salle").value=data.salle; - $("statut-reservation").innerHTML=data.statut; - $("date_evenement").value = data.date_evenement; - $("heure_debut").value=data.heure_debut; - $("heure_fin").value=data.heure_fin; - $("motif_reservation").value=data.motif_reservation; - $("besoin_zoom").checked=data.besoin_zoom; - $("besoin_ordinateur").checked=data.besoin_ordi; - $("lien_zoom").value=data.lien_zoom; - - const refuserReservation = document.querySelector("#refuserReservation"); - const bouton_valider = document.querySelector("#bouton-valider"); - - if((refuserReservation | bouton_valider) && data.statut === "En attente"){ - refuserReservation.style.display = "inline-block"; - bouton_valider.style.display = "inline-block"; - } - - if (id_user != data.employe_id){ - $("bouton-annuler").className = "d-none"; - } + afficherDetailsReservation(data); const modal = new bootstrap.Modal($("modalDetailReservation")); bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide(); diff --git a/gestion_salle/templates/gestion_salle/index.html b/gestion_salle/templates/gestion_salle/index.html index f4fafae..c27a8c6 100644 --- a/gestion_salle/templates/gestion_salle/index.html +++ b/gestion_salle/templates/gestion_salle/index.html @@ -55,5 +55,5 @@ {% block 'js' %} - + {% endblock %} \ No newline at end of file diff --git a/gestion_salle/templates/gestion_salle/parts/modalDetailResevation.html b/gestion_salle/templates/gestion_salle/parts/modalDetailResevation.html index cba39ec..028b1d5 100644 --- a/gestion_salle/templates/gestion_salle/parts/modalDetailResevation.html +++ b/gestion_salle/templates/gestion_salle/parts/modalDetailResevation.html @@ -10,7 +10,7 @@ diff --git a/gestion_salle/urls.py b/gestion_salle/urls.py index a8e3c85..6687343 100644 --- a/gestion_salle/urls.py +++ b/gestion_salle/urls.py @@ -45,5 +45,10 @@ urlpatterns = [ 'liste-reservation-attente', views.liste_reservation_attente, name="liste-reservation-attente" + ), + path( + 'reservation//supprimer', + views.supprimer_reservation, + name="supprimer-reservation", ) ] \ No newline at end of file diff --git a/gestion_salle/views.py b/gestion_salle/views.py index 0b3d05c..f83c2d9 100644 --- a/gestion_salle/views.py +++ b/gestion_salle/views.py @@ -125,19 +125,25 @@ Veuillez vous connecter à la plateforme pour traiter cette demande.""", return render(request, "gestion_salle/index.html", context) +@login_required def liste_reservation(request:HttpRequest): """Vue d'affichage des creneaux disponibles""" - reservations = Reservation.objects.filter(statut = "validee") + try: + employe = Employe.objects.get(user=request.user) + reservations = Reservation.objects.filter( + Q(statut="validee") + | Q(statut="en_attente", employe=employe) + ) + except Employe.DoesNotExist: + reservations = Reservation.objects.filter(statut="validee") + liste_reservation = [] for reservation in reservations: - color = None if reservation.statut == "en_attente": color = "#ffc107" - elif reservation.statut == "validee": - color = "#198754" else: - color = "#dc3545" + color = "#198754" liste_reservation.append({ "guid": reservation.pk, @@ -146,6 +152,7 @@ def liste_reservation(request:HttpRequest): "start": reservation.heure_debut, "end": reservation.heure_fin, "color": color, + "statut": dict(Reservation.STATUT).get(reservation.statut), }) return JsonResponse(liste_reservation, safe=False) @@ -183,6 +190,7 @@ def liste_reservation_attente(request): liste_reservation = [ { **model_to_dict(reservation), + "id": reservation.pk, "employe": f"{reservation.employe.user.first_name} {reservation.employe.user.last_name}", "employe_id": reservation.employe.user.id, "salle": dict(Reservation.TYPE_CHOICES).get(reservation.salle), @@ -193,6 +201,49 @@ def liste_reservation_attente(request): return JsonResponse(liste_reservation, safe=False) + +@login_required +def supprimer_reservation(request: HttpRequest, reservation_id: int): + if request.method != "POST": + return JsonResponse( + {"success": False, "message": "Méthode non autorisée."}, + status=405, + ) + + try: + employe = Employe.objects.get(user=request.user) + except Employe.DoesNotExist: + return JsonResponse( + {"success": False, "message": "Profil employé introuvable."}, + status=403, + ) + + try: + reservation = Reservation.objects.get( + pk=reservation_id, + employe=employe, + ) + except Reservation.DoesNotExist: + return JsonResponse( + {"success": False, "message": "Réservation introuvable ou accès non autorisé."}, + status=404, + ) + + if reservation.statut != "en_attente": + return JsonResponse( + { + "success": False, + "message": "Seules les réservations en attente peuvent être supprimées.", + }, + status=400, + ) + + reservation.delete() + return JsonResponse( + {"success": True, "message": "Votre réservation en attente a été supprimée."} + ) + + def detail_reservation(request:HttpRequest, reservation_id:int): reservation = Reservation.objects.get(id=reservation_id) employe = reservation.employe.user @@ -209,6 +260,8 @@ def detail_reservation(request:HttpRequest, reservation_id:int): 'besoin_zoom': reservation.besoin_zoom, 'besoin_ordinateur': reservation.besoin_ordi, 'lien_zoom': reservation.lien_zoom or '', + 'est_proprietaire': request.user.is_authenticated and reservation.employe.user_id == request.user.id, + 'est_en_attente': reservation.statut == "en_attente", } return JsonResponse(reservation_json, safe=True) -- 2.49.1