From 2521ba44fed09eaf8ba8569e783e1c7468e3f31d Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 19 Jun 2025 03:00:57 +0200 Subject: mode admin et non admin --- public/css/calendar.css | 4 + public/index.html | 25 ---- public/index.php | 31 +++++ public/js/calendar.js | 277 ++---------------------------------- public/js/calendar_admin.js | 331 ++++++++++++++++++++++++++++++++++++++++++++ src/post-ajax.php | 4 +- 6 files changed, 379 insertions(+), 293 deletions(-) delete mode 100644 public/index.html create mode 100644 public/index.php create mode 100644 public/js/calendar_admin.js diff --git a/public/css/calendar.css b/public/css/calendar.css index 035118a..b762a89 100644 --- a/public/css/calendar.css +++ b/public/css/calendar.css @@ -1,3 +1,7 @@ +.event{ + border: 2px double; + border-radius: 5px; +} #calendar_zone{ display: flex; max-width: 1000px; diff --git a/public/index.html b/public/index.html deleted file mode 100644 index bdd7f67..0000000 --- a/public/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - fullcalendar - - - - - - - - - - - - -
-
- - - -
- - diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..abcef90 --- /dev/null +++ b/public/index.php @@ -0,0 +1,31 @@ + + + + + + fullcalendar + + + + + + + + +' . "\n" : '' . "\n"; +?> + + + +
+
+ + + +
+ + diff --git a/public/js/calendar.js b/public/js/calendar.js index 154cdfd..fb26e80 100644 --- a/public/js/calendar.js +++ b/public/js/calendar.js @@ -1,19 +1,3 @@ -/* // à utiliser plus tard? -const current_view = calendar.view; -switch(current_view.type){ - case 'dayGridMonth': - console.log('mois'); - break; - case 'timeGridWeek': - console.log('semaine'); - break; - case 'timeGridDay': - console.log('jour'); - break; - default: - console.log('erreur'); -}*/ - document.addEventListener('DOMContentLoaded', function(){ const calendarEl = document.getElementById('calendar'); let selected_start_string = null; @@ -50,90 +34,13 @@ document.addEventListener('DOMContentLoaded', function(){ nowIndicator: true, // barre rouge pour maintenant select: function(info){ - const aside = document.querySelector('aside'); - let checked = ''; - let input = 'datetime-local'; - - // on veut des chaines de la forme 2025-05-20T07:05 - // il faut retirer les secondes et le fuseau horaire du format ISO, c'est chiant - // on enverra par contre une chaine ISO au serveur pour avoir un enregistrement correct - - let start_value; - let end_value; - const end = new Date(info.endStr); - - console.log(info.startStr); - console.log(info.endStr); - - if(calendar.view.type == 'dayGridMonth'){ - start_value = info.startStr + 'T10:00'; - end.setDate(end.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur - end.setHours(11); - end_value = end.toISOString().split('T')[0] + 'T11:00'; - } - else if(calendar.view.type == 'timeGridWeek' || calendar.view.type == 'timeGridDay'){ - const start_array = info.startStr.split("T"); - const end_array = info.endStr.split("T"); - - // clic sur la ligne "Journée", = 'dayGridMonth' - if(start_array.length == 1){ - checked = 'checked'; - input = 'date'; - start_value = info.startStr; - end.setDate(end.getDate() - 1); - end_value = end.toISOString().split('T')[0]; - } - else if(start_array.length == 2){ - start_value = start_array[0] + "T" + start_array[1].substr(0,5); // format 2025-06-12T10:00 - end_value = end_array[0] + "T" + end_array[1].substr(0,5); - } - else{ - console.log('pas censé se produire'); - return; - } - } - - selected_start_string = start_value; // variable "globale" - - const aside_content = `
-
-

Nouvel évènement

-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - -
`; - aside.innerHTML = aside_content; - calendar.updateSize(); + selected_start_string = info.startStr; // variable "globale" }, //unselect: function(event, view){}, + eventClick: function(info){ const aside = document.querySelector('aside'); const checked = info.event.allDay ? 'checked' : ''; - const input = info.event.allDay ? 'date' : 'datetime-local'; // change des objets Date en chaînes compatibles avec les input function formatDate(date){ @@ -148,38 +55,14 @@ document.addEventListener('DOMContentLoaded', function(){ const formated_start = formatDate(info.event.start); const formated_end = formatDate(info.event.allDay ? getEndMinusOneDay(info.event.end) : info.event.end, info.event.allDay); - const aside_content = `
-
-

Modifier un évènement

-
-
- - - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - -
`; + const aside_content = `
+

` + info.event.title + `

+

` + info.event.extendedProps.description + `

+

Journée entière: ` + (checked ? 'oui' : 'non') + `

+

Début: ` + formated_start + `

+

Fin: ` + formated_end + `

+
`; + aside.innerHTML = aside_content; calendar.updateSize(); }, @@ -198,137 +81,6 @@ document.addEventListener('DOMContentLoaded', function(){ calendar.updateSize(); } - function submitEvent(new_event){ - const event_title = document.getElementById('event_title').value; - const event_description = document.getElementById('event_description').value; - const event_all_day = document.getElementById('event_all_day').checked; - let event_start = document.getElementById('event_start').value; - let event_end = document.getElementById('event_end').value; - const event_color = document.getElementById('event_color').value; // #3788d8 par défaut - const event_id = new_event ? '' : document.getElementById('event_id').value; - - if(event_title.length !== 0 && event_start.length !== 0 && event_end.length !== 0 && event_color.length !== 0 - && (new_event || event_id.length !== 0)) - { - if(event_all_day){ - // on remet le jour de fin exclu - const tmp_object = new Date(event_end); - tmp_object.setDate(tmp_object.getDate() + 1); - event_end = tmp_object.toISOString().split('T')[0]; - } - else{ - event_start = new Date(event_start).toISOString(); - event_end = new Date(event_end).toISOString(); - } - console.log(event_end); - - if(event_start > event_end || (!event_all_day && event_start == event_end)){ - return; - } - - // création - if(new_event){ - const event = { - title: event_title, - description: event_description, - allDay: event_all_day, - start: event_start, - end: event_end, - color: event_color - }; - - fetch('../src/post-ajax.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(event), - }) - .then(response => response.json()) - .then(data => { - if(data.success){ - event.id = data.id; - calendar.addEvent(event); - hideModal(); - } - }) - .catch((error) => { - console.error('Error:', error); - }); - - } - // modification - else{ - const event = calendar.getEventById(event_id); - - if(event){ - const event_copy = { - id: parseInt(event.id), - description: event_description, - title: event_title, - allDay: event_all_day, - start: event_start, - end: event_end, - color: event_color - }; - - fetch('../src/post-ajax.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(event_copy), - }) - .then(response => response.json()) - .then(data => { - if(data.success){ - event.setProp('title', event_title); - event.setExtendedProp('description', event_description); - event.setAllDay(event_all_day); - event.setStart(event_start); - event.setEnd(event_end); - event.setProp('color', event_color); - hideModal(); - } - }) - .catch((error) => { - console.error('Error:', error); - }); - } - else{ - console.log("Événement non trouvé !"); - } - } - } - else{ - // notif input vide - console.log('erreur: input vide'); - } - } - - function checkAllDay(){ - const event_start_input = document.getElementById('event_start'); - const event_end_input = document.getElementById('event_end'); - - const start = event_start_input.value; - const end = event_end_input.value; - - if(document.getElementById('event_all_day').checked){ - event_start_input.type = 'date'; - event_end_input.type = 'date'; - - event_start_input.value = start.split('T')[0]; - event_end_input.value = end.split('T')[0]; - } - else{ - event_start_input.type = 'datetime-local'; - event_end_input.type = 'datetime-local'; - - event_start_input.value = start + 'T10:00'; - event_end_input.value = end + 'T11:00'; - } - } - document.addEventListener('keydown', function(event){ if(event.key === 'Escape') { hideModal(); @@ -340,15 +92,6 @@ document.addEventListener('DOMContentLoaded', function(){ if(event.target.classList.contains('event_close_button')){ hideModal(); } - else if(event.target.classList.contains('event_all_day')){ - checkAllDay(); - } - else if(event.target.classList.contains('submit_new_event')){ - submitEvent(true); - } - else if(event.target.classList.contains('submit_update_event')){ - submitEvent(false); - } }); calendar.render(); diff --git a/public/js/calendar_admin.js b/public/js/calendar_admin.js new file mode 100644 index 0000000..253d127 --- /dev/null +++ b/public/js/calendar_admin.js @@ -0,0 +1,331 @@ +document.addEventListener('DOMContentLoaded', function(){ + const calendarEl = document.getElementById('calendar'); + let selected_start_string = null; + + const calendar = new FullCalendar.Calendar(calendarEl,{ + editable: true, + locale: 'fr', + initialView: 'dayGridMonth', + headerToolbar:{ + left: 'prev,next today', + center: 'title', + right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' + //right: 'dayGridMonth,timeGridWeek' + }, + slotMinWidth: 70, + defaultAllDay: false, + + // numéros de semaine + //weekNumbers: true, + //weekText: 's', + + // vue mois + contentHeight: 600, // après initialisation: calendar.setOption('contentHeight', 650); + //aspectRatio: 1.5, // après initialisation: calendar.setOption('aspectRatio', 1.8); + // pour recalculer la taille au redimensionnement du parent, exécuter: calendar.updateSize() + stickyHeaderDates: true, // garder les en-tête de colonnes lors du scroll + fixedWeekCount: false, // avec false, affiche 4, 5 ou 6 semaines selon le mois + selectable: true, // sélection de jours multiples + navLinks: true, // numéros de jour et de semaines clicables + + // vue semaine + slotEventOverlap: true, // superposition (limitée) de deux évènements simultanés + allDayContent: 'Journée', // texte dans la case "toute la journée" + nowIndicator: true, // barre rouge pour maintenant + + select: function(info){ + selected_start_string = info.startStr; // variable "globale" + const aside = document.querySelector('aside'); + let checked = ''; + let input = 'datetime-local'; + + // on veut des chaines de la forme 2025-05-20T07:05 + // il faut retirer les secondes et le fuseau horaire du format ISO, c'est chiant + // on enverra par contre une chaine ISO au serveur pour avoir un enregistrement correct + + let start_value; + let end_value; + const end = new Date(info.endStr); + + if(calendar.view.type == 'dayGridMonth'){ + start_value = info.startStr + 'T10:00'; + end.setDate(end.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur + end.setHours(11); + end_value = end.toISOString().split('T')[0] + 'T11:00'; + } + else if(calendar.view.type == 'timeGridWeek' || calendar.view.type == 'timeGridDay'){ + const start_array = info.startStr.split("T"); + const end_array = info.endStr.split("T"); + + // clic sur la ligne "Journée", = 'dayGridMonth' + if(start_array.length == 1){ + checked = 'checked'; + input = 'date'; + start_value = info.startStr; + end.setDate(end.getDate() - 1); + end_value = end.toISOString().split('T')[0]; + } + else if(start_array.length == 2){ + start_value = start_array[0] + "T" + start_array[1].substr(0,5); // format 2025-06-12T10:00 + end_value = end_array[0] + "T" + end_array[1].substr(0,5); + } + } + + const aside_content = `
+
+

Nouvel évènement

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
`; + aside.innerHTML = aside_content; + calendar.updateSize(); + }, + //unselect: function(event, view){}, + eventClick: function(info){ + const aside = document.querySelector('aside'); + const checked = info.event.allDay ? 'checked' : ''; + const input = info.event.allDay ? 'date' : 'datetime-local'; + + // change des objets Date en chaînes compatibles avec les input + function formatDate(date){ + return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0') + + (info.event.allDay ? '' : 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0')); + } + function getEndMinusOneDay(date){ + date.setDate(date.getDate() - 1); // jour de fin modifié pour ne pas faire bizarre pour l'utilisateur + return date; + } + + const formated_start = formatDate(info.event.start); + const formated_end = formatDate(info.event.allDay ? getEndMinusOneDay(info.event.end) : info.event.end, info.event.allDay); + + const aside_content = `
+
+

Modifier un évènement

+
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
`; + aside.innerHTML = aside_content; + calendar.updateSize(); + }, + viewDidMount: function(info){ // déclenché lorsque qu'une nouvelle vue est chargée (mois, semaine...) + if(selected_start_string){ + calendar.gotoDate(new Date(selected_start_string)); + } + }, + //datesSet: function(info){}, // déclenché lorsque des dates affichées sont chargées (= comme viewDidMount + changement de date) + events: '../src/load-events.php' // fichier PHP qui retourne les événements + }); + + function hideModal(){ + const aside = document.querySelector('aside'); + aside.innerHTML = ''; + calendar.updateSize(); + } + + function submitEvent(new_event){ + const event_title = document.getElementById('event_title').value; + const event_description = document.getElementById('event_description').value; + const event_all_day = document.getElementById('event_all_day').checked; + let event_start = document.getElementById('event_start').value; + let event_end = document.getElementById('event_end').value; + const event_color = document.getElementById('event_color').value; // #3788d8 par défaut + const event_id = new_event ? '' : document.getElementById('event_id').value; + + if(event_title.length !== 0 && event_start.length !== 0 && event_end.length !== 0 && event_color.length !== 0 + && (new_event || event_id.length !== 0)) + { + if(event_all_day){ + // on remet le jour de fin exclu + const tmp_object = new Date(event_end); + tmp_object.setDate(tmp_object.getDate() + 1); + event_end = tmp_object.toISOString().split('T')[0]; + } + else{ + event_start = new Date(event_start).toISOString(); + event_end = new Date(event_end).toISOString(); + } + console.log(event_end); + + if(event_start > event_end || (!event_all_day && event_start == event_end)){ + return; + } + + // création + if(new_event){ + const event = { + title: event_title, + description: event_description, + allDay: event_all_day, + start: event_start, + end: event_end, + color: event_color + }; + + fetch('../src/post-ajax.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(event), + }) + .then(response => response.json()) + .then(data => { + if(data.success){ + event.id = data.id; + calendar.addEvent(event); + hideModal(); + } + }) + .catch((error) => { + console.error('Error:', error); + }); + + } + // modification + else{ + const event = calendar.getEventById(event_id); + + if(event){ + const event_copy = { + id: parseInt(event.id), + description: event_description, + title: event_title, + allDay: event_all_day, + start: event_start, + end: event_end, + color: event_color + }; + + fetch('../src/post-ajax.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(event_copy), + }) + .then(response => response.json()) + .then(data => { + if(data.success){ + event.setProp('title', event_title); + event.setExtendedProp('description', event_description); + event.setAllDay(event_all_day); + event.setStart(event_start); + event.setEnd(event_end); + event.setProp('color', event_color); + hideModal(); + } + }) + .catch((error) => { + console.error('Error:', error); + }); + } + else{ + console.log("Événement non trouvé !"); + } + } + } + else{ + // notif input vide + console.log('erreur: input vide'); + } + } + + function checkAllDay(){ + const event_start_input = document.getElementById('event_start'); + const event_end_input = document.getElementById('event_end'); + + const start = event_start_input.value; + const end = event_end_input.value; + + if(document.getElementById('event_all_day').checked){ + event_start_input.type = 'date'; + event_end_input.type = 'date'; + + event_start_input.value = start.split('T')[0]; + event_end_input.value = end.split('T')[0]; + } + else{ + event_start_input.type = 'datetime-local'; + event_end_input.type = 'datetime-local'; + + event_start_input.value = start + 'T10:00'; + event_end_input.value = end + 'T11:00'; + } + } + + document.addEventListener('keydown', function(event){ + if(event.key === 'Escape') { + hideModal(); + } + }); + + // technique de la délégation d'événements pour utiliser un bouton ajouté dynamiquement + document.addEventListener('click', function(event){ + if(event.target.classList.contains('event_close_button')){ + hideModal(); + } + else if(event.target.classList.contains('event_all_day')){ + checkAllDay(); + } + else if(event.target.classList.contains('submit_new_event')){ + submitEvent(true); + } + else if(event.target.classList.contains('submit_update_event')){ + submitEvent(false); + } + }); + + calendar.render(); +}); \ No newline at end of file diff --git a/src/post-ajax.php b/src/post-ajax.php index df5a01a..bedfed5 100644 --- a/src/post-ajax.php +++ b/src/post-ajax.php @@ -1,5 +1,7 @@