@@ -, +, @@ - Log in to the OPAC and go to "your curbside pickups." - Under the "Schedule a pickup" tab you should see only the option to select a library. - When you select a library the "Pickup date" field should appear. - When you select a date the time-selection buttons and the notes field should appear. - Hovering over a time should trigger the "Appointments available" tooltip. - Clicking a time should cause the "button" to turn green with a check-mark icon. - Submit a pickup request and confirm that it is saved correctly. - Return to the "Schedule a pickup" form and confirm that selecting the same library again triggers a message, "You already have a pickup scheduled for this library." - Select another library and another date. - Switch your library selection to the library you already have a request for. The date, time, and notes fields should be hidden again and the same message triggered about already having a pickup scheduled. --- .../prog/en/modules/circ/curbside_pickups.tt | 5 + .../en/modules/opac-curbside-pickups.tt | 342 +++++++++++------- 2 files changed, 209 insertions(+), 138 deletions(-) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/curbside_pickups.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/curbside_pickups.tt @@ -10,6 +10,9 @@ [% INCLUDE 'doc-head-open.inc' %] Curbside pickups › Circulation › Koha - +[% FILTER collapse %] + +[% END %] [% INCLUDE 'doc-head-close.inc' %] [% BLOCK cssinclude %][% END %] @@ -173,8 +231,8 @@
  1. - - [% FOR p IN policies %] @@ -182,16 +240,17 @@ [% END %] +
    Required
  2. -
  3. - +
  4. + - Required +
    Required
  5. -
  6. +
  7. -
  8. +
  9. @@ -265,146 +324,153 @@ existingPickupMoments[pickup.branchcode].push(pickupMoment); }); - $("#pickup-branch option").each(function(){ - if ( $(this).val() != "" && !policies[$(this).val()].enabled ) { - $(this).prop("disabled", "disabled"); - $(this).attr("title", _("You don't have waiting holds at this library")); - } - }); - - $('#pickup-branch').on('change', function() { - let branchcode = $(this).val(); - - let existing_pickup = pickup_exists_in.indexOf(branchcode) != -1; + $(document).ready(function() { + $("#pickup-branch option").each(function(){ + if ( $(this).val() != "" && !policies[$(this).val()].enabled ) { + $(this).prop("disabled", "disabled"); + $(this).attr("title", _("You don't have waiting holds at this library")); + } + }); - $('#pickup-date').val(""); - $('#pickup-time').val(""); - $('#pickup-times').hide(); - $('#schedule-pickup-button').prop('disabled', true); + $('#pickup-branch').on('change', function() { + let branchcode = $(this).val(); - if (existing_pickup) { - $('#existing-pickup-warning').show(); - $('#pickup-date').prop("disabled", true); - } else { - $('#existing-pickup-warning').hide(); - $('#pickup-date').prop("disabled", branchcode == ""); - } - }); + let existing_pickup = pickup_exists_in.indexOf(branchcode) != -1; - $("#pickup-date").on('change', function() { + $('#pickup-date').val(""); + $('#pickup-time').val(""); + $('#pickup-times').hide(); + $('#schedule-pickup-button').prop('disabled', true); - $('#pickup-times').empty(); - $('#schedule-pickup-button').prop( 'disabled', 1 ); + if (existing_pickup) { + $('#existing-pickup-warning').show(); + $("#pickup_date_item,#pickup_notes_item").hide(); + $('#pickup-date').prop("disabled", true); + } else { + $('#existing-pickup-warning').hide(); + $("#pickup_date_item").show(); + $('#pickup-date').prop("disabled", branchcode == ""); + } + }); - var currentDate = $(this).val(); - let branchcode = $("#pickup-branch").val(); - let policy = policies[branchcode]; + const pickupDate = document.getElementById("pickup-date"); + pickupDate._flatpickr.config.onClose.push(function( selectedDates, dateStr, instance ){ + /* Here we add an onClose event to the existing flatpickr instance */ + /* It fires after the user has selected a date from the calendar popup */ + $('#pickup-times').html(""); + $('#schedule-pickup-button').prop( 'disabled', 1 ); - let selectedDate = dayjs(currentDate, get_dateformat_str(dateformat_pref).toUpperCase()); + var currentDate = dateStr; + let branchcode = $("#pickup-branch").val(); + let policy = policies[branchcode]; - let pickupSlots = []; - let available_count = 0; - let dow = selectedDate.day(); // Sunday is 0 (at least for now) - if (!policy.slots_per_day[dow]){ - $('#pickup-times').html("
    "+_("No pickup time defined for this day.")+"
    "); - return; - } + let selectedDate = dayjs(currentDate, get_dateformat_str(dateformat_pref).toUpperCase()); - policy.slots_per_day[dow].forEach(function(slot){ - let pickup_interval = policy.pickup_interval; - if (!pickup_interval) { + let pickupSlots = []; + let available_count = 0; + let dow = selectedDate.day(); // Sunday is 0 (at least for now) + if (!policy.slots_per_day[dow]){ $('#pickup-times').html("
    "+_("No pickup time defined for this day.")+"
    "); return; } - let listStartMoment = selectedDate.hour(slot.start_hour).minute(slot.start_minute); - let listEndMoment = selectedDate.hour(slot.end_hour).minute(slot.end_minute); - - let keep_going = true; - let now = dayjs(); - - // Initialize pickup slots starting at opening time - let pickupIntervalStartMoment = listStartMoment; - let pickupIntervalEndMoment = listStartMoment.add(pickup_interval, 'minutes'); - while (keep_going) { - let available = true; - let display_slot = true; - - if (pickupIntervalStartMoment.isBefore(now)) { - // Slots in the past are unavailable - available = false; - display_slot = false; + policy.slots_per_day[dow].forEach(function(slot){ + let pickup_interval = policy.pickup_interval; + if (!pickup_interval) { + $('#pickup-times').html("
    "+_("No pickup time defined for this day.")+"
    "); + return; } - if (pickupIntervalEndMoment.isAfter(listEndMoment)) { - // Slots after the end of pickup times for the day are unavailable - available = false; + let listStartMoment = selectedDate.hour(slot.start_hour).minute(slot.start_minute); + let listEndMoment = selectedDate.hour(slot.end_hour).minute(slot.end_minute); + + let keep_going = true; + let now = dayjs(); + + // Initialize pickup slots starting at opening time + let pickupIntervalStartMoment = listStartMoment; + let pickupIntervalEndMoment = listStartMoment.add(pickup_interval, 'minutes'); + while (keep_going) { + let available = true; + let display_slot = true; + + if (pickupIntervalStartMoment.isBefore(now)) { + // Slots in the past are unavailable + available = false; + display_slot = false; + } + + if (pickupIntervalEndMoment.isAfter(listEndMoment)) { + // Slots after the end of pickup times for the day are unavailable + available = false; + } + + let pickups_scheduled = 0; + + if (existingPickupMoments[branchcode]){ + existingPickupMoments[branchcode].forEach(function(pickupMoment){ + // An existing pickup time + if (pickupMoment.isSameOrAfter(pickupIntervalStartMoment) && pickupMoment.isBefore(pickupIntervalEndMoment)) { + // This calculated pickup is in use by another scheduled pickup + pickups_scheduled++; + } + }); + } + + if (pickups_scheduled >= policy.patrons_per_interval) { + available = false; + } + + if ( display_slot ) { + pickupSlots.push( + { + "available": available, + "moment": pickupIntervalStartMoment, + "pickups_scheduled": pickups_scheduled + } + ); + } + + if ( available ) { + available_count++; + } + + pickupIntervalStartMoment = pickupIntervalEndMoment; + pickupIntervalEndMoment = pickupIntervalStartMoment.add(pickup_interval, 'minutes'); + if (pickupIntervalEndMoment.isAfter(listEndMoment)) { + // This latest slot is after the end of pickup times for the day, so we can stop + keep_going = false; + } } - let pickups_scheduled = 0; - - if (existingPickupMoments[branchcode]){ - existingPickupMoments[branchcode].forEach(function(pickupMoment){ - // An existing pickup time - if (pickupMoment.isSameOrAfter(pickupIntervalStartMoment) && pickupMoment.isBefore(pickupIntervalEndMoment)) { - // This calculated pickup is in use by another scheduled pickup - pickups_scheduled++; - } - }); - } - - if (pickups_scheduled >= policy.patrons_per_interval) { - available = false; - } - - if ( display_slot ) { - pickupSlots.push( - { - "available": available, - "moment": pickupIntervalStartMoment, - "pickups_scheduled": pickups_scheduled - } - ); - } - - if ( available ) { - available_count++; - } - - pickupIntervalStartMoment = pickupIntervalEndMoment; - pickupIntervalEndMoment = pickupIntervalStartMoment.add(pickup_interval, 'minutes'); - if (pickupIntervalEndMoment.isAfter(listEndMoment)) { - // This latest slot is after the end of pickup times for the day, so we can stop - keep_going = false; - } + $('#schedule-pickup-button').prop( 'disabled', available_count <= 0 ); + }); + + for (let i = 0; i < pickupSlots.length; i++) { + let pickupSlot = pickupSlots[i]; + let optText = pickupSlot.moment.format("HH:mm"); + let optValue = pickupSlot.moment.format("YYYY-MM-DD HH:mm:ss"); + let pickups_scheduled = pickupSlot.pickups_scheduled; + let pickups_available = policy.patrons_per_interval - pickups_scheduled; + let disabled = pickupSlot.available ? "" : "disabled"; + $("#pickup-times").append(` `); } - $('#schedule-pickup-button').prop( 'disabled', available_count <= 0 ); + $("#pickup_notes_item,#pickup-times").show(); }); - for (let i = 0; i < pickupSlots.length; i++) { - let pickupSlot = pickupSlots[i]; - let optText = pickupSlot.moment.format("HH:mm"); - let optValue = pickupSlot.moment.format("YYYY-MM-DD HH:mm:ss"); - let pickups_scheduled = pickupSlot.pickups_scheduled; - let disabled = pickupSlot.available ? "" : "disabled"; - $("#pickup-times").append(` `); - } - - $('#pickup-times').show(); - }); - - - $(document).ready(function() { - $("#pickup-times").hide(); + $("#pickup_date_item,#pickup_notes_item,#pickup-times").hide(); $("#create-pickup").on('submit', function(){ if ( ! $("input[type='radio']:checked").length ) { - alert(_("Please select a date and a pickup time")) + alert(_("Please select a date and a pickup time")); return false; } return true; }); + $("#pickup-times").tooltip({ + selector: ".pickup_select" + }); }); [% END %] --