4 [% USE TablesSettings %]
5 [% INCLUDE 'doc-head-open.inc' %]
7 Curbside pickup › Administration › Koha
9 [% INCLUDE 'doc-head-close.inc' %]
12 border: 2px solid #b9d8d9;
19 <body id="admin_curbside_pickup" class="admin">
20 [% INCLUDE 'header.inc' %]
21 [% INCLUDE 'cities-admin-search.inc' %]
23 [% USE format_minutes = format('%02d') %]
24 [% MACRO minutes_format BLOCK %][% IF m != "" %][% format_minutes(m) | html %][% END %][% END %]
25 <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
28 <a href="/cgi-bin/koha/mainpage.pl">Home</a>
31 <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
35 <a href="#" aria-current="page">
42 <div class="main container-fluid">
44 <div class="col-sm-10 col-sm-push-2">
47 [% FOR m IN messages %]
48 <div class="dialog [% m.type | html %]">
51 <span>[% m.code | html %]</span>
58 <h1>Curbside pickup configuration</h1>
60 <form method="post" class="form">
61 <div id="curbside_pickup_tabs" class="toptabs">
62 <ul class="nav nav-tabs" role="tablist">
63 [% FOREACH l IN libraries %]
65 <li role="presentation" class="active">
67 <li role="presentation">
69 <a href="#conf-[% l.branchcode | uri %]" aria-controls="conf-[% l.branchcode | html %]" role="tab" data-toggle="tab">[% l.branchname | html %]</a>
74 <div class="tab-content">
75 [% FOREACH l IN libraries %]
76 [% SET branchcode = l.branchcode %]
78 <div id="conf-[% l.branchcode | html %]" role="tabpanel" class="tab-pane active">
80 <div id="conf-[% l.branchcode | html %]" role="tabpanel" class="tab-pane">
82 <fieldset class="rows" style="float: none;">
85 <label for="enable-[% l.branchcode | html %]">Enable: </label>
86 [% IF policies.$branchcode.enabled %]
87 <input name="enable-[% l.branchcode | html %]" id="enable-[% l.branchcode | html %]" value="1" type="checkbox" checked>
89 <input name="enable-[% l.branchcode | html %]" id="enable-[% l.branchcode | html %]" value="1" type="checkbox">
91 <span class="hint">Enable curbside pickup.<span>
95 <label for="interval-[% l.branchcode | html %]">Pickup interval: </label>
96 <input name="interval-[% l.branchcode | html %]" id="interval-[% l.branchcode | html %]" value="[% policies.$branchcode.pickup_interval | html %]" type="text">
97 <span class="hint">Number of minutes each curbside pickup interaction will take.</span>
101 <label for="max-per-interval-[% l.branchcode | html %]">Maximum patrons per interval: </label>
102 <input name="max-per-interval-[% l.branchcode | html %]" id="max-per-interval-[% l.branchcode | html %]" value="[% policies.$branchcode.patrons_per_interval | html %]" type="text">
103 <span class="hint">Maximum number of simultaneus pickups per interval.</span>
107 <label for="patron-scheduled-[% l.branchcode | html %]">Patron-scheduled pickup: </label>
108 [% IF policies.$branchcode.patron_scheduled_pickup %]
109 <input name="patron-scheduled-[% l.branchcode | html %]" id="patron-scheduled-[% l.branchcode | html %]" value="1" type="checkbox" checked>
111 <input name="patron-scheduled-[% l.branchcode | html %]" id="patron-scheduled-[% l.branchcode | html %]" value="1" type="checkbox">
113 <span class="hint">Enable patrons to schedule their own curbside pickups.</span>
117 <label for="enable-waiting-holds-only-[% l.branchcode | html %]">Enable for waiting holds only: </label>
118 [% IF policies.$branchcode.enable_waiting_holds_only %]
119 <input name="enable-waiting-holds-only-[% l.branchcode | html %]" id="enable-waiting-holds-only-[% l.branchcode | html %]" value="1" type="checkbox" checked>
121 <input name="enable-waiting-holds-only-[% l.branchcode | html %]" id="enable-waiting-holds-only-[% l.branchcode | html %]" value="1" type="checkbox">
123 <span class="hint">Enable only if the patron has waiting holds.</span>
128 <fieldset class="rows" style="float: none;">
129 <legend>Curbside pickup hours</legend>
131 <em>Times should be in 24-hour format (00:00 to 23:59).</em>
133 <ol class="pickup_hours"></ol>
137 <label>New slot:</label>
139 <select id="day-[% l.branchcode | html %]">
140 <option value="0">Sunday</option>
141 <option value="1">Monday</option>
142 <option value="2">Tuesday</option>
143 <option value="3">Wednesday</option>
144 <option value="4">Thursday</option>
145 <option value="5">Friday</option>
146 <option value="6">Saturday</option>
148 From <input type="text" size="5" class="noEnterSubmit" id="new-start-[% l.branchcode | html %]" placeholder="00:00" />
149 to <input type="text" size="5" class="noEnterSubmit" id="new-end-[% l.branchcode | html %]" placeholder="23:55" />
152 <input type="button" class="add-new-slot" data-branchcode="[% l.branchcode | html %]" value="Add" />
153 <span id="invalid_slot_warning" style="display:none;">Invalid format for this new slot, must be '00:00 to 23:59'.</span>
164 <input type="hidden" name="op" value="save" />
166 <fieldset class="action">
167 <input type="submit" value="Save configuration" />
173 </div> <!-- /.col-sm-10.col-sm-push-2 -->
175 <div class="col-sm-2 col-sm-pull-10">
177 [% INCLUDE 'admin-menu.inc' %]
179 </div> <!-- /.col-sm-2.col-sm-pull-10 -->
180 </div> <!-- /.row -->
182 [% MACRO jsinclude BLOCK %]
183 [% Asset.js("js/admin-menu.js") | $raw %]
186 let opening_slots = {};
188 [% FOR l IN libraries %]
189 [% SET branchcode = l.branchcode %]
191 [% FOR p IN policies.$branchcode.opening_slots %]
192 slots.push('%s-%s-%s'.format("[% p.day | html %]", format_hhmm("[% p.start_hour | html %]:[% p.start_minute | html %]"), format_hhmm("[% p.end_hour | html %]:[% p.end_minute | html %]")));
194 opening_slots["[% l.branchcode | html %]"] = slots;
197 function format_hhmm(hhmm){
199 [ hh, mm ] = hhmm.split(':');
200 return String(hh).padStart(2, '0') + ':' + String(mm).padStart(2, '0');
202 function format_slot(slot){
204 [ day, start, end ] = slot.split("-");
205 return format_hhmm(start) + _(" to ") + format_hhmm(end);
207 function delete_slot(node, branchcode){
208 let slot = $(node).find('input').val();
209 opening_slots[branchcode] = $.grep(opening_slots[branchcode], function(elt, index) {
212 refresh_pickup_hours(branchcode);
214 function refresh_pickup_hours(branchcode) {
215 let slots_per_day = {};
216 opening_slots[branchcode].forEach(function(slot){
218 [ day, start, end ] = slot.split("-");
219 if(!slots_per_day[day]) slots_per_day[day] = [];
220 slots_per_day[day].push(slot);
223 $("#conf-"+branchcode).find(".pickup_hours li").remove();
225 Object.keys(slots_per_day).forEach(function(day){
226 let li_node = $('<li><label>'+get_day_lib(day)+'<label></li>');
227 slots_per_day[day].forEach(function(slot) {
228 let span_node = $('<span class="pickup-slot"></span>');
229 span_node.append('<input type="hidden" name="pickup-slot-'+branchcode+'" value="'+slot+'"/>');
230 span_node.append('<span>'+format_slot(slot)+'</span>');
232 let delete_link = $('<a href="#" on><i class="fa fa-trash" aria-hidden="true"></i>').on('click', function(e){ e.preventDefault(); delete_slot($(this).closest('li'), branchcode); });
233 span_node.append(delete_link);
235 span_node.appendTo(li_node);
237 li_node.appendTo($("#conf-"+branchcode).find(".pickup_hours"));
240 function get_day_lib(day){
253 lib = _("Wednesday");
268 $(document).ready(function(){
269 [% FOR l IN libraries %]
270 refresh_pickup_hours("[% l.branchcode | html %]");
273 $(".add-new-slot").on("click", function(){
274 let branchcode = $(this).data('branchcode');
275 let day = $("#day-" + branchcode).val();
276 let start = $("#new-start-" + branchcode).val();
277 let end = $("#new-end-" + branchcode).val();
279 let start_hour, start_minute, end_hour, end_minute;
280 [ start_hour, start_minute ] = start.split(":");
281 [ end_hour, end_minute ] = end.split(":");
282 if ( start_hour === undefined
283 || start_minute === undefined
284 || end_hour === undefined
285 || end_minute === undefined
286 || isNaN(parseInt(start_hour))
287 || isNaN(parseInt(end_hour))
288 || isNaN(parseInt(start_minute))
289 || isNaN(parseInt(end_minute))
290 || start_hour > 23 || start_minute > 59
291 || end_hour > 23 || end_minute > 59
293 $("#invalid_slot_warning").show();
296 $("#invalid_slot_warning").hide();
299 let new_slot = day + '-' + start + '-' + end;
300 if ( opening_slots[branchcode].indexOf(new_slot) < 0 )
301 opening_slots[branchcode].push(new_slot);
303 refresh_pickup_hours(branchcode);
308 [% INCLUDE 'intranet-bottom.inc' %]