nodebb-plugin-calendar-onekite 1.4.5 → 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-calendar-onekite",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
package/plugin.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "Calendar Onekite",
4
4
  "description": "Calendrier + réservation de matériel + validation admin + paiement HelloAsso pour NodeBB v4",
5
5
  "url": "",
6
- "version": "1.4.5",
6
+ "version": "1.4.6",
7
7
  "library": "./library.js",
8
8
  "staticDirs": {
9
9
  "static": "static"
@@ -1,301 +1,42 @@
1
- 'use strict';
2
-
3
- $(document).ready(function () {
4
- if (!$('#calendar').length) return;
5
-
6
- const CalendarPage = {
7
-
8
- canBook: false,
9
-
10
- init: function () {
11
- this.prepareModals();
12
- this.checkPermissions();
13
- this.initCalendar();
14
- },
15
-
16
- checkPermissions: function () {
17
- $.get('/api/calendar/permissions/book').then(res => {
18
- CalendarPage.canBook = !!(res && res.allow);
19
- });
20
- },
21
-
22
- prepareModals: function () {
23
- $('.calendar-modal').hide();
24
- $('.calendar-modal .calendar-close').on('click', function () {
25
- $(this).closest('.calendar-modal').fadeOut();
26
- });
27
- },
28
-
29
- initCalendar: function () {
30
- const calendarEl = document.getElementById('calendar');
31
-
32
- const calendar = new FullCalendar.Calendar(calendarEl, {
33
- themeSystem: 'bootstrap5',
34
- initialView: 'dayGridMonth',
35
- locale: 'fr',
36
- height: 'auto',
37
- selectable: true,
38
- headerToolbar: {
39
- left: 'prev,next today',
40
- center: 'title',
41
- right: 'dayGridMonth,timeGridWeek,listWeek'
42
- },
43
-
44
- events: (info, success, fail) => {
45
- $.get('/api/calendar/events', { start: info.startStr, end: info.endStr })
46
- .then(events => {
47
- success(events.map(ev => ({
48
- id: ev.eid,
49
- title: ev.title,
50
- start: ev.start,
51
- end: ev.end,
52
- allDay: ev.allDay == 1,
53
- extendedProps: ev
54
- })));
55
- })
56
- .catch(fail);
57
- },
58
-
59
- dateClick: info => {
60
- CalendarPage.openCreateEventModal(info.dateStr);
61
- },
62
-
63
- eventClick: info => {
64
- CalendarPage.openEventModal(info.event.extendedProps);
65
- }
66
- });
67
-
68
- calendar.render();
69
-
70
- // bouton nouvel event
71
- $.get('/api/calendar/permissions/create').then(res => {
72
- if (!res || !res.allow) {
73
- $('#calendar-new-event').hide();
74
- } else {
75
- $('#calendar-new-event').on('click', () => {
76
- CalendarPage.openCreateEventModal();
77
- });
78
- }
79
- });
80
- },
81
-
82
- /* -------- MODAL EVENT -------- */
83
-
84
- openCreateEventModal: function (dateStr) {
85
- const modal = $('#calendar-event-modal');
86
-
87
- $('#event-modal-title').text('Créer un événement');
88
- $('#event-title').val('');
89
- $('#event-description').val('');
90
- const base = dateStr || new Date().toISOString().slice(0, 10);
91
- $('#event-start').val(base + 'T09:00');
92
- $('#event-end').val(base + 'T11:00');
93
- $('#event-allDay').prop('checked', false);
94
- $('#event-location').val('');
95
- $('#event-bookingEnabled').prop('checked', false);
96
- $('#booking-items').empty();
97
-
98
- $('#event-save').off('click').on('click', () => {
99
- CalendarPage.saveEvent();
100
- });
101
-
102
- $('#event-delete').hide();
103
- $('#event-reserve').hide();
104
-
105
- $('#event-add-item').off('click').on('click', () => {
106
- CalendarPage.addBookingItemRow();
107
- });
108
-
109
- modal.fadeIn();
110
- },
111
-
112
- openEventModal: function (eventData) {
113
- const modal = $('#calendar-event-modal');
114
-
115
- $('#event-modal-title').text('Événement : ' + eventData.title);
116
- $('#event-title').val(eventData.title);
117
- $('#event-description').val(eventData.description || '');
118
- $('#event-start').val(eventData.start.replace('Z', ''));
119
- $('#event-end').val(eventData.end.replace('Z', ''));
120
- $('#event-allDay').prop('checked', eventData.allDay == 1);
121
- $('#event-location').val(eventData.location || '');
122
- $('#event-bookingEnabled').prop('checked', eventData.bookingEnabled == 1);
123
-
124
- CalendarPage.renderBookingItems(eventData.bookingItems || []);
125
-
126
- $('#event-add-item').off('click').on('click', () => {
127
- CalendarPage.addBookingItemRow();
128
- });
129
-
130
- $('#event-save').off('click').on('click', () => {
131
- CalendarPage.updateEvent(eventData.eid);
132
- });
133
-
134
- $('#event-delete').show().off('click').on('click', () => {
135
- bootbox.confirm('Supprimer cet événement ?', ok => {
136
- if (!ok) return;
137
- $.ajax({ url: '/api/calendar/event/' + eventData.eid, method: 'DELETE' })
138
- .then(() => location.reload());
139
- });
140
- });
141
-
142
- if (CalendarPage.canBook && Number(eventData.bookingEnabled)) {
143
- $('#event-reserve').show().off('click').on('click', () => {
144
- CalendarPage.openReserveModal(eventData.eid);
145
- });
146
- } else {
147
- $('#event-reserve').hide();
148
- }
149
-
150
- modal.fadeIn();
151
- },
152
-
153
- saveEvent: function () {
154
- const data = CalendarPage.collectEventForm();
155
- $.ajax({
156
- url: '/api/calendar/event',
157
- method: 'POST',
158
- contentType: 'application/json',
159
- data: JSON.stringify(data),
160
- }).then(() => location.reload())
161
- .catch(err => app.alertError(err.responseJSON?.error || err.message));
162
- },
163
-
164
- updateEvent: function (eid) {
165
- const data = CalendarPage.collectEventForm();
166
- $.ajax({
167
- url: '/api/calendar/event/' + eid,
168
- method: 'PUT',
169
- contentType: 'application/json',
170
- data: JSON.stringify(data),
171
- }).then(() => location.reload())
172
- .catch(err => app.alertError(err.responseJSON?.error || err.message));
173
- },
174
-
175
- collectEventForm: function () {
176
- const items = [];
177
- $('#booking-items .booking-item-row').each(function () {
178
- const row = $(this);
179
- const total = Number(row.find('.item-total').val() || 0);
180
- if (!total) return;
181
-
182
- items.push({
183
- id: row.find('.item-id').val(),
184
- name: row.find('.item-name').val(),
185
- total,
186
- reserved: Number(row.find('.item-reserved').val() || 0),
187
- reservedTemp: Number(row.find('.item-reservedTemp').val() || 0),
188
- price: Number(row.find('.item-price').val() || 0),
189
- pickupLocation: row.find('.item-pickup').val() || ''
190
- });
191
- });
192
-
193
- return {
194
- title: $('#event-title').val(),
195
- description: $('#event-description').val(),
196
- start: $('#event-start').val(),
197
- end: $('#event-end').val(),
198
- allDay: $('#event-allDay').is(':checked'),
199
- location: $('#event-location').val(),
200
- bookingEnabled: $('#event-bookingEnabled').is(':checked'),
201
- bookingItems: items
202
- };
203
- },
204
-
205
- renderBookingItems: function (items) {
206
- const container = $('#booking-items');
207
- container.empty();
208
- (items || []).forEach(item => CalendarPage.addBookingItemRow(item));
209
- },
210
-
211
- addBookingItemRow: function (item = {}) {
212
- const row = $(`
213
- <div class="booking-item-row">
214
- <input type="text" class="item-id form-control" placeholder="ID" value="${item.id || ''}">
215
- <input type="text" class="item-name form-control" placeholder="Nom matériel" value="${item.name || ''}">
216
- <input type="number" class="item-total form-control" placeholder="Total" value="${item.total || 0}">
217
- <input type="number" class="item-price form-control" placeholder="Prix €" step="0.01" value="${item.price || 0}">
218
- <input type="text" class="item-pickup form-control" placeholder="Lieu retrait" value="${item.pickupLocation || ''}">
219
- <input type="hidden" class="item-reserved" value="${item.reserved || 0}">
220
- <input type="hidden" class="item-reservedTemp" value="${item.reservedTemp || 0}">
221
- <button class="btn btn-danger btn-sm item-remove">✕</button>
222
- </div>
223
- `);
224
-
225
- row.find('.item-remove').on('click', () => row.remove());
226
- $('#booking-items').append(row);
227
- },
228
-
229
- /* -------- MODAL RÉSERVATION -------- */
230
-
231
- openReserveModal: function (eid) {
232
- $.get('/api/calendar/event/' + eid).then(eventData => {
233
- const modal = $('#calendar-reserve-modal');
234
-
235
- $('#reserve-title').text(eventData.title);
236
-
237
- const items = eventData.bookingItems || [];
238
- if (!items.length || !Number(eventData.bookingEnabled)) {
239
- $('#reserve-items').html('<p>Aucun matériel réservable pour cet événement.</p>');
240
- $('#reserve-confirm').hide();
241
- } else {
242
- let html = '<ul>';
243
- items.forEach((item, index) => {
244
- const pickup = item.pickupLocation || 'Lieu de retrait non précisé';
245
- html += `
246
- <li>
247
- <label>
248
- <input type="radio" name="reserve-item" value="${item.id}" ${index === 0 ? 'checked' : ''}>
249
- <strong>${item.name}</strong>
250
- ${item.price ? `– ${item.price} €/jour` : ''}
251
- <br><small>📍 Retrait : ${pickup}</small>
252
- </label>
253
- </li>`;
254
- });
255
- html += '</ul>';
256
- $('#reserve-items').html(html);
257
- $('#reserve-confirm').show();
258
- }
259
-
260
- const today = new Date().toISOString().slice(0, 10);
261
- $('#reserve-start').val(today);
262
- $('#reserve-end').val(today);
263
- $('#reserve-quantity').val(1);
264
-
265
- $('#reserve-confirm').off('click').on('click', () => {
266
- CalendarPage.sendReservation(eid);
267
- });
1
+ define('plugins/nodebb-plugin-calendar-onekite/static/js/calendar', [
2
+ 'api',
3
+ 'alerts',
4
+ ], function (api, alerts) {
5
+ 'use strict';
6
+
7
+ function init() {
8
+ // jQuery est fourni par NodeBB sur les pages rendues via buildHeader
9
+ const $ = window.jQuery;
10
+ if (!$) {
11
+ // fallback: on évite le crash
12
+ console.error('[calendar-onekite] jQuery not found');
13
+ return;
14
+ }
268
15
 
269
- modal.fadeIn();
16
+ // Exemple: bind bouton "nouvel événement"
17
+ $('#calendar-new-event')
18
+ .off('click.calendarOnekite')
19
+ .on('click.calendarOnekite', function () {
20
+ // TODO: ouvre ton modal / formulaire
21
+ alerts.success('Clique OK: handler actif ✅');
270
22
  });
271
- },
272
23
 
273
- sendReservation: function (eid) {
274
- const itemId = $('input[name="reserve-item"]:checked').val();
275
- const quantity = Number($('#reserve-quantity').val() || 1);
276
- const dateStart = $('#reserve-start').val();
277
- const dateEnd = $('#reserve-end').val();
24
+ // Si tu as d'autres binds / initialisation calendrier, fais-les ici
25
+ }
278
26
 
279
- if (!itemId) return app.alertError('Sélectionnez un matériel.');
280
- if (!quantity || quantity <= 0) return app.alertError('Quantité invalide.');
281
- if (!dateStart || !dateEnd) return app.alertError('Merci de renseigner les dates.');
282
- if (dateEnd < dateStart) return app.alertError('La date de fin doit être ≥ la date de début.');
27
+ // important: ajaxify SPA
28
+ $(window).on('action:ajaxify.end', function () {
29
+ // page /calendar
30
+ if (ajaxify?.data?.template?.includes('calendar')) {
31
+ init();
32
+ }
33
+ });
283
34
 
284
- $.ajax({
285
- url: '/api/calendar/event/' + eid + '/book',
286
- method: 'POST',
287
- contentType: 'application/json',
288
- data: JSON.stringify({ itemId, quantity, dateStart, dateEnd }),
289
- })
290
- .then(res => {
291
- app.alertSuccess(res.message || 'Demande envoyée.');
292
- $('#calendar-reserve-modal').fadeOut();
293
- })
294
- .catch(err => {
295
- app.alertError(err.responseJSON?.error || err.message);
296
- });
35
+ $(function () {
36
+ if (ajaxify?.data?.template?.includes('calendar')) {
37
+ init();
297
38
  }
298
- };
39
+ });
299
40
 
300
- CalendarPage.init();
41
+ return { init };
301
42
  });
@@ -26,4 +26,9 @@
26
26
  </div>
27
27
 
28
28
  <button id="calendar-onekite-save" class="btn btn-primary">Enregistrer</button>
29
- </div>
29
+ </div>
30
+ <script>
31
+ require(['plugins/nodebb-plugin-calendar-onekite/static/js/calendar'], function (Calendar) {
32
+ Calendar.init && Calendar.init();
33
+ });
34
+ </script>
@@ -84,5 +84,8 @@
84
84
  </div>
85
85
  </div>
86
86
 
87
- <link rel="stylesheet" href="/plugins/nodebb-plugin-calendar-onekite/static/style.css">
88
- <script src="/plugins/nodebb-plugin-calendar-onekite/static/js/calendar.js"></script>
87
+ <script>
88
+ require(['plugins/nodebb-plugin-calendar-onekite/static/js/calendar'], function (Calendar) {
89
+ Calendar.init && Calendar.init();
90
+ });
91
+ </script>