nodebb-plugin-onekite-calendar 1.0.31 → 1.0.33

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-onekite-calendar",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "FullCalendar-based equipment reservation workflow with admin approval & HelloAsso payment for NodeBB",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/plugin.json CHANGED
@@ -39,5 +39,5 @@
39
39
  "acpScripts": [
40
40
  "public/admin.js"
41
41
  ],
42
- "version": "1.0.31"
42
+ "version": "1.0.33"
43
43
  }
package/public/client.js CHANGED
@@ -36,6 +36,10 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
36
36
  // interactions or quick re-renders.
37
37
  let isDialogOpen = false;
38
38
 
39
+ // Avoid duplicate toasts when the same validation fails both client-side and
40
+ // server-side (e.g. "today or past" date rule).
41
+ let lastDateRuleToastAt = 0;
42
+
39
43
  function escapeHtml(str) {
40
44
  return String(str)
41
45
  .replace(/&/g, '&')
@@ -1193,6 +1197,7 @@ function toDatetimeLocalValue(date) {
1193
1197
  const startDateCheck = toLocalYmd(info.start);
1194
1198
  const todayCheck = toLocalYmd(new Date());
1195
1199
  if (startDateCheck <= todayCheck) {
1200
+ lastDateRuleToastAt = Date.now();
1196
1201
  showAlert('error', "Impossible de réserver pour aujourd’hui ou une date passée.");
1197
1202
  calendar.unselect();
1198
1203
  isDialogOpen = false;
@@ -1243,7 +1248,10 @@ function toDatetimeLocalValue(date) {
1243
1248
  } else if (code === '409') {
1244
1249
  showAlert('error', 'Impossible : au moins un matériel est déjà réservé ou en attente sur cette période.');
1245
1250
  } else if (code === '400' && payload && (payload.error === 'date-too-soon' || payload.code === 'date-too-soon')) {
1246
- showAlert('error', String(payload.message || "Impossible de réserver pour aujourd’hui ou une date passée."));
1251
+ // If we already showed the client-side toast a moment ago, avoid a duplicate.
1252
+ if (!lastDateRuleToastAt || (Date.now() - lastDateRuleToastAt) > 1500) {
1253
+ showAlert('error', String(payload.message || "Impossible de réserver pour aujourd’hui ou une date passée."));
1254
+ }
1247
1255
  } else {
1248
1256
  const msgRaw = payload && (payload.message || payload.error || payload.msg)
1249
1257
  ? String(payload.message || payload.error || payload.msg)
@@ -1299,8 +1307,12 @@ function toDatetimeLocalValue(date) {
1299
1307
  return;
1300
1308
  }
1301
1309
 
1302
- const end = new Date(start.getTime() + 24 * 60 * 60 * 1000);
1303
- calendar.select(start, end);
1310
+ // IMPORTANT: Do not call `calendar.select()` here.
1311
+ // On mobile (and depending on FullCalendar behavior), a simple day click can already
1312
+ // trigger the `select` callback. Calling `calendar.select()` would fire `select` a second
1313
+ // time, causing duplicate toasts and duplicate dialogs.
1314
+ // We rely on FullCalendar's built-in selection on click.
1315
+ return;
1304
1316
  },
1305
1317
 
1306
1318
  eventClick: async function (info) {