View | Details | Raw Unified | Return to bug 37707
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/prog/css/src/bookings.scss (-1 / +1 lines)
Lines 10-13 Link Here
10
            );
10
            );
11
        }
11
        }
12
    }
12
    }
13
}
13
}
(-)a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss (+13 lines)
Lines 1103-1108 $leadClashTrail: #e5d4f5 !default; Link Here
1103
    }
1103
    }
1104
}
1104
}
1105
1105
1106
// Booking conflict feedback message styles
1107
.booking-conflict-feedback {
1108
    // Override Bootstrap's default alert padding and sizing for compact display
1109
    padding: 0.5rem 0.75rem;
1110
    margin-top: 0.5rem;
1111
    margin-bottom: 0 !important; // Override Bootstrap's default 1rem margin-bottom
1112
    min-height: 1.25rem;
1113
    text-align: center;
1114
1115
    // Bootstrap's .alert-danger, .alert-warning, and .alert-info classes
1116
    // provide the color schemes via CSS variables when combined with .alert
1117
}
1118
1106
.input-warning {
1119
.input-warning {
1107
    background-color: #ff9;
1120
    background-color: #ff9;
1108
    border-color: #900;
1121
    border-color: #900;
(-)a/koha-tmpl/intranet-tmpl/prog/js/modals/place_booking.js (-42 / +384 lines)
Lines 922-927 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
922
                    );
922
                    );
923
                }
923
                }
924
924
925
                // Create feedback message container below the calendar
926
                let feedbackDiv = periodPicker.calendarContainer.querySelector(
927
                    ".booking-conflict-feedback"
928
                );
929
                if (!feedbackDiv) {
930
                    feedbackDiv = document.createElement("div");
931
                    feedbackDiv.className =
932
                        "booking-conflict-feedback alert d-none";
933
                    periodPicker.calendarContainer.appendChild(feedbackDiv);
934
                }
935
925
                // Add hints for days before the start range and after the end range
936
                // Add hints for days before the start range and after the end range
926
                periodPicker.calendarContainer.addEventListener(
937
                periodPicker.calendarContainer.addEventListener(
927
                    "mouseover",
938
                    "mouseover",
Lines 941-949 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
941
                            const leadStart = startDate
952
                            const leadStart = startDate
942
                                ? startDate.subtract(leadDays, "day")
953
                                ? startDate.subtract(leadDays, "day")
943
                                : hoverDate.subtract(leadDays, "day");
954
                                : hoverDate.subtract(leadDays, "day");
944
                            const leadEnd = startDate ? startDate : hoverDate;
955
                            const leadEnd = startDate
945
                            const trailStart = hoverDate;
956
                                ? startDate.subtract(1, "day")
946
                            const trailEnd = hoverDate.add(trailDays, "day");
957
                                : hoverDate.subtract(1, "day");
958
                            const trailStart = startDate
959
                                ? hoverDate.add(1, "day")
960
                                : hoverDate.add(1, "day");
961
                            const trailEnd = startDate
962
                                ? hoverDate.add(trailDays, "day")
963
                                : hoverDate.add(trailDays, "day");
947
964
948
                            // BIDIRECTIONAL ENHANCEMENT: Collect closest bookings for visual feedback
965
                            // BIDIRECTIONAL ENHANCEMENT: Collect closest bookings for visual feedback
949
                            // and check for mathematical conflicts in a single pass
966
                            // and check for mathematical conflicts in a single pass
Lines 956-961 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
956
                            let leadDisable = false;
973
                            let leadDisable = false;
957
                            let trailDisable = false;
974
                            let trailDisable = false;
958
975
976
                            // Track conflict reasons for messaging
977
                            let leadConflictReason = {
978
                                withTrail: false,
979
                                withLead: false,
980
                                withBooking: false,
981
                            };
982
                            let trailConflictReason = {
983
                                withTrail: false,
984
                                withLead: false,
985
                                withBooking: false,
986
                            };
987
959
                            bookings.forEach(booking => {
988
                            bookings.forEach(booking => {
960
                                // Skip if we're editing this booking
989
                                // Skip if we're editing this booking
961
                                if (
990
                                if (
Lines 1000-1007 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1000
                                    "day"
1029
                                    "day"
1001
                                );
1030
                                );
1002
1031
1003
                                // Check if new booking's LEAD period overlaps with existing booking's TRAIL period
1032
                                // Check if new booking's LEAD period overlaps with existing booking
1004
                                if (!periodPicker.selectedDates[0]) {
1033
                                if (!periodPicker.selectedDates[0]) {
1034
                                    // Check overlap with existing booking's trail period
1005
                                    if (
1035
                                    if (
1006
                                        leadStart.isSameOrBefore(
1036
                                        leadStart.isSameOrBefore(
1007
                                            existingTrailEnd
1037
                                            existingTrailEnd
Lines 1011-1021 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1011
                                        )
1041
                                        )
1012
                                    ) {
1042
                                    ) {
1013
                                        leadDisable = true;
1043
                                        leadDisable = true;
1044
                                        leadConflictReason.withTrail = true;
1045
                                    }
1046
                                    // Check overlap with existing booking's lead period
1047
                                    else if (
1048
                                        leadStart.isSameOrBefore(
1049
                                            existingLeadEnd
1050
                                        ) &&
1051
                                        leadEnd.isSameOrAfter(existingLeadStart)
1052
                                    ) {
1053
                                        leadDisable = true;
1054
                                        leadConflictReason.withLead = true;
1055
                                    }
1056
                                    // Check overlap with existing booking itself
1057
                                    else if (
1058
                                        leadStart.isSameOrBefore(bookingEnd) &&
1059
                                        leadEnd.isSameOrAfter(bookingStart)
1060
                                    ) {
1061
                                        leadDisable = true;
1062
                                        leadConflictReason.withBooking = true;
1014
                                    }
1063
                                    }
1015
                                }
1064
                                }
1016
1065
1017
                                // Check if new booking's TRAIL period overlaps with existing booking's LEAD period
1066
                                // Check if new booking's TRAIL period overlaps with existing booking
1018
                                if (periodPicker.selectedDates[0]) {
1067
                                if (periodPicker.selectedDates[0]) {
1068
                                    // Check overlap with existing booking's lead period
1019
                                    if (
1069
                                    if (
1020
                                        trailStart.isSameOrBefore(
1070
                                        trailStart.isSameOrBefore(
1021
                                            existingLeadEnd
1071
                                            existingLeadEnd
Lines 1025-1030 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1025
                                        )
1075
                                        )
1026
                                    ) {
1076
                                    ) {
1027
                                        trailDisable = true;
1077
                                        trailDisable = true;
1078
                                        trailConflictReason.withLead = true;
1079
                                    }
1080
                                    // Check overlap with existing booking's trail period
1081
                                    else if (
1082
                                        trailStart.isSameOrBefore(
1083
                                            existingTrailEnd
1084
                                        ) &&
1085
                                        trailEnd.isSameOrAfter(
1086
                                            existingTrailStart
1087
                                        )
1088
                                    ) {
1089
                                        trailDisable = true;
1090
                                        trailConflictReason.withTrail = true;
1091
                                    }
1092
                                    // Check overlap with existing booking itself
1093
                                    else if (
1094
                                        trailStart.isSameOrBefore(bookingEnd) &&
1095
                                        trailEnd.isSameOrAfter(bookingStart)
1096
                                    ) {
1097
                                        trailDisable = true;
1098
                                        trailConflictReason.withBooking = true;
1028
                                    }
1099
                                    }
1029
                                }
1100
                                }
1030
1101
Lines 1058-1063 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1058
                                }
1129
                                }
1059
                            });
1130
                            });
1060
1131
1132
                            // Work through all days in view and add classes appropraitely based on hovered date
1061
                            periodPicker.calendarContainer
1133
                            periodPicker.calendarContainer
1062
                                .querySelectorAll(".flatpickr-day")
1134
                                .querySelectorAll(".flatpickr-day")
1063
                                .forEach(function (dayElem) {
1135
                                .forEach(function (dayElem) {
Lines 1085-1119 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1085
                                        "existingBookingTrailEnd"
1157
                                        "existingBookingTrailEnd"
1086
                                    );
1158
                                    );
1087
1159
1088
                                    // Apply new booking's lead/trail period classes
1160
                                    // Apply proposed booking's lead/trail period classes
1089
                                    dayElem.classList.toggle(
1161
                                    // Only apply lead classes if lead period > 0
1090
                                        "leadRangeStart",
1162
                                    if (leadDays > 0) {
1091
                                        elemDate.isSame(leadStart)
1163
                                        dayElem.classList.toggle(
1092
                                    );
1164
                                            "leadRangeStart",
1093
                                    dayElem.classList.toggle(
1165
                                            elemDate.isSame(leadStart)
1094
                                        "leadRange",
1166
                                        );
1095
                                        elemDate.isSameOrAfter(leadStart) &&
1167
                                        dayElem.classList.toggle(
1096
                                            elemDate.isBefore(leadEnd)
1168
                                            "leadRange",
1097
                                    );
1169
                                            elemDate.isSameOrAfter(leadStart) &&
1098
                                    dayElem.classList.toggle(
1170
                                                elemDate.isSameOrBefore(leadEnd)
1099
                                        "leadRangeEnd",
1171
                                        );
1100
                                        elemDate.isSame(leadEnd)
1172
                                        dayElem.classList.toggle(
1101
                                    );
1173
                                            "leadRangeEnd",
1102
                                    dayElem.classList.toggle(
1174
                                            elemDate.isSame(leadEnd)
1103
                                        "trailRangeStart",
1175
                                        );
1104
                                        elemDate.isSame(trailStart)
1176
                                    }
1105
                                    );
1106
                                    dayElem.classList.toggle(
1107
                                        "trailRange",
1108
                                        elemDate.isAfter(trailStart) &&
1109
                                            elemDate.isSameOrBefore(trailEnd)
1110
                                    );
1111
                                    dayElem.classList.toggle(
1112
                                        "trailRangeEnd",
1113
                                        elemDate.isSame(trailEnd)
1114
                                    );
1115
1177
1116
                                    // BIDIRECTIONAL: Show closest existing booking's trail period
1178
                                    // Only apply trail classes if trail period > 0
1179
                                    if (trailDays > 0) {
1180
                                        dayElem.classList.toggle(
1181
                                            "trailRangeStart",
1182
                                            elemDate.isSame(trailStart)
1183
                                        );
1184
                                        dayElem.classList.toggle(
1185
                                            "trailRange",
1186
                                            elemDate.isSameOrAfter(
1187
                                                trailStart
1188
                                            ) &&
1189
                                                elemDate.isSameOrBefore(
1190
                                                    trailEnd
1191
                                                )
1192
                                        );
1193
                                        dayElem.classList.toggle(
1194
                                            "trailRangeEnd",
1195
                                            elemDate.isSame(trailEnd)
1196
                                        );
1197
                                    }
1198
1199
                                    // Show closest preceding existing booking's trail period
1117
                                    if (closestBeforeBooking && trailDays > 0) {
1200
                                    if (closestBeforeBooking && trailDays > 0) {
1118
                                        const existingTrailStart =
1201
                                        const existingTrailStart =
1119
                                            closestBeforeBooking.end.add(
1202
                                            closestBeforeBooking.end.add(
Lines 1159-1165 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1159
                                        }
1242
                                        }
1160
                                    }
1243
                                    }
1161
1244
1162
                                    // BIDIRECTIONAL: Show closest existing booking's lead period
1245
                                    // Show closest following existing booking's lead period
1163
                                    if (closestAfterBooking && leadDays > 0) {
1246
                                    if (closestAfterBooking && leadDays > 0) {
1164
                                        const existingLeadStart =
1247
                                        const existingLeadStart =
1165
                                            closestAfterBooking.start.subtract(
1248
                                            closestAfterBooking.start.subtract(
Lines 1203-1209 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1203
                                        }
1286
                                        }
1204
                                    }
1287
                                    }
1205
1288
1206
                                    // Check for conflicts with flatpickr-disabled dates (original behavior)
1289
                                    // Check for conflicts with flatpickr-disabled dates
1207
                                    if (
1290
                                    if (
1208
                                        dayElem.classList.contains(
1291
                                        dayElem.classList.contains(
1209
                                            "flatpickr-disabled"
1292
                                            "flatpickr-disabled"
Lines 1212-1223 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1212
                                        if (
1295
                                        if (
1213
                                            !periodPicker.selectedDates[0] &&
1296
                                            !periodPicker.selectedDates[0] &&
1214
                                            elemDate.isSameOrAfter(leadStart) &&
1297
                                            elemDate.isSameOrAfter(leadStart) &&
1215
                                            elemDate.isBefore(leadEnd)
1298
                                            elemDate.isSameOrBefore(leadEnd)
1216
                                        ) {
1299
                                        ) {
1217
                                            leadDisable = true;
1300
                                            leadDisable = true;
1218
                                        }
1301
                                        }
1219
                                        if (
1302
                                        if (
1220
                                            elemDate.isAfter(trailStart) &&
1303
                                            periodPicker.selectedDates[0] &&
1304
                                            elemDate.isSameOrAfter(
1305
                                                trailStart
1306
                                            ) &&
1221
                                            elemDate.isSameOrBefore(trailEnd)
1307
                                            elemDate.isSameOrBefore(trailEnd)
1222
                                        ) {
1308
                                        ) {
1223
                                            // Only consider this a conflict if the disabled date is within the max date range
1309
                                            // Only consider this a conflict if the disabled date is within the max date range
Lines 1238-1244 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1238
                                        }
1324
                                        }
1239
                                    }
1325
                                    }
1240
1326
1241
                                    // BIDIRECTIONAL: Check for conflicts with existing booking's trail period
1327
                                    // Check for conflicts with existing booking's trail period
1242
                                    if (
1328
                                    if (
1243
                                        !periodPicker.selectedDates[0] &&
1329
                                        !periodPicker.selectedDates[0] &&
1244
                                        dayElem.classList.contains(
1330
                                        dayElem.classList.contains(
Lines 1248-1268 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1248
                                        // New booking's lead period overlaps with existing booking's trail
1334
                                        // New booking's lead period overlaps with existing booking's trail
1249
                                        if (
1335
                                        if (
1250
                                            elemDate.isSameOrAfter(leadStart) &&
1336
                                            elemDate.isSameOrAfter(leadStart) &&
1251
                                            elemDate.isBefore(leadEnd)
1337
                                            elemDate.isSameOrBefore(leadEnd)
1252
                                        ) {
1338
                                        ) {
1253
                                            leadDisable = true;
1339
                                            leadDisable = true;
1254
                                        }
1340
                                        }
1255
                                    }
1341
                                    }
1256
1342
1257
                                    // BIDIRECTIONAL: Check for conflicts with existing booking's lead period
1343
                                    // Check for conflicts with existing booking's lead period
1258
                                    if (
1344
                                    if (
1345
                                        periodPicker.selectedDates[0] &&
1259
                                        dayElem.classList.contains(
1346
                                        dayElem.classList.contains(
1260
                                            "existingBookingLead"
1347
                                            "existingBookingLead"
1261
                                        )
1348
                                        )
1262
                                    ) {
1349
                                    ) {
1263
                                        // New booking's trail period overlaps with existing booking's lead
1350
                                        // New booking's trail period overlaps with existing booking's lead
1264
                                        if (
1351
                                        if (
1265
                                            elemDate.isAfter(trailStart) &&
1352
                                            elemDate.isSameOrAfter(
1353
                                                trailStart
1354
                                            ) &&
1266
                                            elemDate.isSameOrBefore(trailEnd)
1355
                                            elemDate.isSameOrBefore(trailEnd)
1267
                                        ) {
1356
                                        ) {
1268
                                            trailDisable = true;
1357
                                            trailDisable = true;
Lines 1278-1283 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1278
                                    );
1367
                                    );
1279
                                });
1368
                                });
1280
1369
1370
                            // Additional check for hovering directly on existing booking's lead/trail periods
1371
                            // If hovering on an existing booking's lead period when selecting start date, block selection
1372
                            if (
1373
                                !periodPicker.selectedDates[0] &&
1374
                                target.classList.contains("existingBookingLead")
1375
                            ) {
1376
                                leadDisable = true;
1377
                            }
1378
1379
                            // If hovering on an existing booking's trail period when selecting end date, block selection
1380
                            if (
1381
                                periodPicker.selectedDates[0] &&
1382
                                target.classList.contains(
1383
                                    "existingBookingTrail"
1384
                                )
1385
                            ) {
1386
                                trailDisable = true;
1387
                            }
1388
1281
                            if (leadDisable) {
1389
                            if (leadDisable) {
1282
                                target.classList.add("leadDisable");
1390
                                target.classList.add("leadDisable");
1283
                            }
1391
                            }
Lines 1291-1296 $("#placeBookingModal").on("show.bs.modal", function (e) { Link Here
1291
                                    true
1399
                                    true
1292
                                );
1400
                                );
1293
                            }
1401
                            }
1402
1403
                            // Update feedback message
1404
                            const feedbackDiv =
1405
                                periodPicker.calendarContainer.querySelector(
1406
                                    ".booking-conflict-feedback"
1407
                                );
1408
                            if (feedbackDiv) {
1409
                                let message = "";
1410
                                let messageType = "info"; // info, warning, error
1411
1412
                                // Determine what the hovered date is (needed for both error and info messages)
1413
                                const today = dayjs().startOf("day");
1414
                                const isDisabled =
1415
                                    target.classList.contains(
1416
                                        "flatpickr-disabled"
1417
                                    );
1418
                                const isInExistingLead =
1419
                                    target.classList.contains(
1420
                                        "existingBookingLead"
1421
                                    );
1422
                                const isInExistingTrail =
1423
                                    target.classList.contains(
1424
                                        "existingBookingTrail"
1425
                                    );
1426
1427
                                // Generate appropriate feedback messages based on conflicts
1428
                                if (leadDisable || trailDisable) {
1429
                                    messageType = "error";
1430
1431
                                    // When selecting START date (no date selected yet)
1432
                                    if (!periodPicker.selectedDates[0]) {
1433
                                        // Check direct state first (what IS this date?)
1434
                                        if (hoverDate.isBefore(today)) {
1435
                                            message = __(
1436
                                                "Cannot select: date is in the past"
1437
                                            );
1438
                                        } else if (isDisabled) {
1439
                                            message = __(
1440
                                                "Cannot select: this date is part of an existing booking"
1441
                                            );
1442
                                        } else if (isInExistingLead) {
1443
                                            message = __(
1444
                                                "Cannot select: this date is part of an existing booking's lead period"
1445
                                            );
1446
                                        } else if (isInExistingTrail) {
1447
                                            message = __(
1448
                                                "Cannot select: this date is part of an existing booking's trail period"
1449
                                            );
1450
                                        }
1451
                                        // Then check calculated lead period conflicts
1452
                                        else if (
1453
                                            leadDays > 0 &&
1454
                                            leadStart.isSameOrBefore(today)
1455
                                        ) {
1456
                                            message =
1457
                                                __("Cannot select") +
1458
                                                ": " +
1459
                                                __(
1460
                                                    "insufficient lead time (%s days required before start)"
1461
                                                ).format(leadDays);
1462
                                        } else if (leadDays > 0) {
1463
                                            // Use mathematical conflict detection (works across month boundaries)
1464
                                            if (leadConflictReason.withTrail) {
1465
                                                message =
1466
                                                    __("Cannot select") +
1467
                                                    ": " +
1468
                                                    __(
1469
                                                        "lead period (%s days before start) conflicts with an existing booking's trail period"
1470
                                                    ).format(leadDays);
1471
                                            } else if (
1472
                                                leadConflictReason.withLead
1473
                                            ) {
1474
                                                message =
1475
                                                    __("Cannot select") +
1476
                                                    ": " +
1477
                                                    __(
1478
                                                        "lead period (%s days before start) conflicts with an existing booking's lead period"
1479
                                                    ).format(leadDays);
1480
                                            } else if (
1481
                                                leadConflictReason.withBooking
1482
                                            ) {
1483
                                                message =
1484
                                                    __("Cannot select") +
1485
                                                    ": " +
1486
                                                    __(
1487
                                                        "lead period (%s days before start) conflicts with an existing booking"
1488
                                                    ).format(leadDays);
1489
                                            }
1490
                                        } else {
1491
                                            message = __(
1492
                                                "Cannot select: conflicts with an existing booking"
1493
                                            );
1494
                                        }
1495
                                    }
1496
                                    // When selecting END date (start date already selected)
1497
                                    else if (periodPicker.selectedDates[0]) {
1498
                                        // Check direct state first (what IS this date?)
1499
                                        if (isDisabled) {
1500
                                            message = __(
1501
                                                "Cannot select: this date is part of an existing booking"
1502
                                            );
1503
                                        } else if (isInExistingLead) {
1504
                                            message = __(
1505
                                                "Cannot select: this date is part of an existing booking's lead period"
1506
                                            );
1507
                                        } else if (isInExistingTrail) {
1508
                                            message = __(
1509
                                                "Cannot select: this date is part of an existing booking's trail period"
1510
                                            );
1511
                                        }
1512
                                        // Then check calculated trail period conflicts
1513
                                        else if (trailDays > 0) {
1514
                                            // Use mathematical conflict detection (works across month boundaries)
1515
                                            if (trailConflictReason.withLead) {
1516
                                                message =
1517
                                                    __("Cannot select") +
1518
                                                    ": " +
1519
                                                    __(
1520
                                                        "trail period (%s days after return) conflicts with an existing booking's lead period"
1521
                                                    ).format(trailDays);
1522
                                            } else if (
1523
                                                trailConflictReason.withTrail
1524
                                            ) {
1525
                                                message =
1526
                                                    __("Cannot select") +
1527
                                                    ": " +
1528
                                                    __(
1529
                                                        "trail period (%s days after return) conflicts with an existing booking's trail period"
1530
                                                    ).format(trailDays);
1531
                                            } else if (
1532
                                                trailConflictReason.withBooking
1533
                                            ) {
1534
                                                message =
1535
                                                    __("Cannot select") +
1536
                                                    ": " +
1537
                                                    __(
1538
                                                        "trail period (%s days after return) conflicts with an existing booking"
1539
                                                    ).format(trailDays);
1540
                                            }
1541
                                        } else {
1542
                                            message = __(
1543
                                                "Cannot select: conflicts with existing an booking"
1544
                                            );
1545
                                        }
1546
                                    }
1547
                                } else {
1548
                                    // Show helpful info messages when no conflicts
1549
                                    if (!periodPicker.selectedDates[0]) {
1550
                                        // When selecting start date, show both lead and trail info
1551
                                        if (leadDays > 0 && trailDays > 0) {
1552
                                            message =
1553
                                                __("Selecting start date") +
1554
                                                ". " +
1555
                                                __(
1556
                                                    "Lead period: %s days before start"
1557
                                                ).format(leadDays) +
1558
                                                ". " +
1559
                                                __(
1560
                                                    "Trail period: %s days after return"
1561
                                                ).format(trailDays);
1562
                                        } else if (leadDays > 0) {
1563
                                            message =
1564
                                                __("Selecting start date") +
1565
                                                ". " +
1566
                                                __(
1567
                                                    "Lead period: %s days before start"
1568
                                                ).format(leadDays);
1569
                                        } else if (trailDays > 0) {
1570
                                            message =
1571
                                                __("Selecting start date") +
1572
                                                ". " +
1573
                                                __(
1574
                                                    "Trail period: %s days after return"
1575
                                                ).format(trailDays);
1576
                                        } else {
1577
                                            message = __(
1578
                                                "Selecting start date"
1579
                                            );
1580
                                        }
1581
                                        messageType = "info";
1582
                                    } else {
1583
                                        if (trailDays > 0) {
1584
                                            message =
1585
                                                __("Selecting end date") +
1586
                                                ". " +
1587
                                                __(
1588
                                                    "Trail period: %s days after return"
1589
                                                ).format(trailDays);
1590
                                        } else {
1591
                                            message = __("Selecting end date");
1592
                                        }
1593
                                        messageType = "info";
1594
                                    }
1595
1596
                                    // Show additional context if hovering over existing booking periods
1597
                                    if (isInExistingLead) {
1598
                                        message +=
1599
                                            " • " +
1600
                                            __(
1601
                                                "hovering existing booking's lead period"
1602
                                            );
1603
                                    } else if (isInExistingTrail) {
1604
                                        message +=
1605
                                            " • " +
1606
                                            __(
1607
                                                "hovering existing booking's trail period"
1608
                                            );
1609
                                    }
1610
                                }
1611
1612
                                feedbackDiv.textContent = message;
1613
                                feedbackDiv.classList.remove(
1614
                                    "alert-danger",
1615
                                    "alert-warning",
1616
                                    "alert-info"
1617
                                );
1618
1619
                                if (message) {
1620
                                    feedbackDiv.classList.remove("d-none");
1621
                                    // Apply appropriate Bootstrap alert class based on message type
1622
                                    if (messageType === "error") {
1623
                                        feedbackDiv.classList.add(
1624
                                            "alert-danger"
1625
                                        );
1626
                                    } else if (messageType === "warning") {
1627
                                        feedbackDiv.classList.add(
1628
                                            "alert-warning"
1629
                                        );
1630
                                    } else {
1631
                                        feedbackDiv.classList.add("alert-info");
1632
                                    }
1633
                                } else {
1634
                                    feedbackDiv.classList.add("d-none");
1635
                                }
1636
                            }
1294
                        }
1637
                        }
1295
                    }
1638
                    }
1296
                );
1639
                );
1297
- 

Return to bug 37707