Bug 30650: Allow to restrict curbside pickup for waiting holds only
[koha-ffzg.git] / koha-tmpl / intranet-tmpl / prog / en / modules / admin / curbside_pickup.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% SET footerjs = 1 %]
4 [% USE TablesSettings %]
5 [% INCLUDE 'doc-head-open.inc' %]
6 <title>
7     Curbside pickup &rsaquo; Administration &rsaquo; Koha
8 </title>
9 [% INCLUDE 'doc-head-close.inc' %]
10 <style>
11     .pickup-slot {
12         border: 2px solid #b9d8d9;
13         padding: 0 .1em;
14         margin: 0 .1em;
15     }
16 </style>
17 </head>
18
19 <body id="admin_curbside_pickup" class="admin">
20 [% INCLUDE 'header.inc' %]
21 [% INCLUDE 'cities-admin-search.inc' %]
22
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">
26     <ol>
27         <li>
28             <a href="/cgi-bin/koha/mainpage.pl">Home</a>
29         </li>
30         <li>
31             <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
32         </li>
33
34         <li>
35             <a href="#" aria-current="page">
36                 Curbside pickup
37             </a>
38         </li>
39     </ol>
40 </nav>
41
42 <div class="main container-fluid">
43     <div class="row">
44         <div class="col-sm-10 col-sm-push-2">
45             <main>
46
47 [% FOR m IN messages %]
48     <div class="dialog [% m.type | html %]">
49         [% SWITCH m.code %]
50         [% CASE %]
51             <span>[% m.code | html %]</span>
52         [% END %]
53     </div>
54 [% END %]
55
56 [% IF op == 'list' %]
57
58     <h1>Curbside pickup configuration</h1>
59
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 %]
64                     [% IF loop.first %]
65                     <li role="presentation" class="active">
66                     [% ELSE %]
67                     <li role="presentation">
68                     [% END %]
69                         <a href="#conf-[% l.branchcode | uri %]" aria-controls="conf-[% l.branchcode | html %]" role="tab" data-toggle="tab">[% l.branchname | html %]</a>
70                     </li>
71                 [% END %]
72             </ul>
73
74             <div class="tab-content">
75                 [% FOREACH l IN libraries %]
76                     [% SET branchcode = l.branchcode %]
77                     [% IF loop.first %]
78                     <div id="conf-[% l.branchcode | html %]" role="tabpanel" class="tab-pane active">
79                     [% ELSE %]
80                     <div id="conf-[% l.branchcode | html %]" role="tabpanel" class="tab-pane">
81                     [% END %]
82                         <fieldset class="rows" style="float: none;">
83                             <ol>
84                                 <li>
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>
88                                     [% ELSE %]
89                                         <input name="enable-[% l.branchcode | html %]" id="enable-[% l.branchcode | html %]" value="1" type="checkbox">
90                                     [% END %]
91                                     <span class="hint">Enable curbside pickup.<span>
92                                 </li>
93
94                                 <li>
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>
98                                 </li>
99
100                                 <li>
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>
104                                 </li>
105
106                                 <li>
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>
110                                     [% ELSE %]
111                                         <input name="patron-scheduled-[% l.branchcode | html %]" id="patron-scheduled-[% l.branchcode | html %]" value="1" type="checkbox">
112                                     [% END %]
113                                     <span class="hint">Enable patrons to schedule their own curbside pickups.</span>
114                                 </li>
115
116                                 <li>
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>
120                                     [% ELSE %]
121                                         <input name="enable-waiting-holds-only-[% l.branchcode | html %]" id="enable-waiting-holds-only-[% l.branchcode | html %]" value="1" type="checkbox">
122                                     [% END %]
123                                     <span class="hint">Enable only if the patron has waiting holds.</span>
124                                 </li>
125                             </ol>
126                         </fieldset>
127
128                         <fieldset class="rows" style="float: none;">
129                             <legend>Curbside pickup hours</legend>
130
131                             <em>Times should be in 24-hour format (00:00 to 23:59).</em>
132
133                             <ol class="pickup_hours"></ol>
134
135                             <ol>
136                                 <li>
137                                     <label>New slot:</label>
138                                     <div>
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>
147                                             <span>
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" />
150                                             </span>
151                                         </select>
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>
154                                     </div>
155                                 </li>
156
157                             </ol>
158                         </fieldset>
159                     </div>
160                 [% END %]
161             </div>
162         </div>
163
164         <input type="hidden" name="op" value="save" />
165
166         <fieldset class="action">
167             <input type="submit" value="Save configuration" />
168         </fieldset>
169     </form>
170 [% END %]
171
172             </main>
173         </div> <!-- /.col-sm-10.col-sm-push-2 -->
174
175         <div class="col-sm-2 col-sm-pull-10">
176             <aside>
177                 [% INCLUDE 'admin-menu.inc' %]
178             </aside>
179         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
180      </div> <!-- /.row -->
181
182 [% MACRO jsinclude BLOCK %]
183     [% Asset.js("js/admin-menu.js") | $raw %]
184     <script>
185
186         let opening_slots = {};
187         let slots;
188         [% FOR l IN libraries %]
189             [% SET branchcode = l.branchcode %]
190             slots = [];
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 %]")));
193             [% END %]
194             opening_slots["[% l.branchcode | html %]"] = slots;
195         [% END %]
196
197         function format_hhmm(hhmm){
198             let hh, mm;
199             [ hh, mm ] = hhmm.split(':');
200             return String(hh).padStart(2, '0') + ':' + String(mm).padStart(2, '0');
201         }
202         function format_slot(slot){
203             let day, start, end;
204             [ day, start, end ] = slot.split("-");
205             return format_hhmm(start) + _(" to ") + format_hhmm(end);
206         }
207         function delete_slot(node, branchcode){
208             let slot = $(node).find('input').val();
209             opening_slots[branchcode] = $.grep(opening_slots[branchcode], function(elt, index) {
210                 return elt !== slot;
211             });
212             refresh_pickup_hours(branchcode);
213         }
214         function refresh_pickup_hours(branchcode) {
215             let slots_per_day = {};
216             opening_slots[branchcode].forEach(function(slot){
217                 let day, start, end;
218                 [ day, start, end ] = slot.split("-");
219                 if(!slots_per_day[day]) slots_per_day[day] = [];
220                 slots_per_day[day].push(slot);
221             });
222
223             $("#conf-"+branchcode).find(".pickup_hours li").remove();
224
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>');
231
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);
234
235                     span_node.appendTo(li_node);
236                 });
237                 li_node.appendTo($("#conf-"+branchcode).find(".pickup_hours"));
238             });
239         }
240         function get_day_lib(day){
241             let lib;
242             switch(day){
243             case '0':
244                 lib = _("Sunday");
245                 break;
246             case '1':
247                 lib = _("Monday");
248                 break;
249             case '2':
250                 lib = _("Tuesday");
251                 break;
252             case '3':
253                 lib = _("Wednesday");
254                 break;
255             case '4':
256                 lib = _("Thursday");
257                 break;
258             case '5':
259                 lib = _("Friday");
260                 break;
261             case '6':
262                 lib = _("Saturday");
263                 break;
264             }
265             return lib;
266         }
267
268         $(document).ready(function(){
269             [% FOR l IN libraries %]
270                 refresh_pickup_hours("[% l.branchcode | html %]");
271             [% END %]
272
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();
278
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
292                   ) {
293                     $("#invalid_slot_warning").show();
294                     return;
295                 } else {
296                     $("#invalid_slot_warning").hide();
297                 }
298
299                 let new_slot = day + '-' + start + '-' + end;
300                 if ( opening_slots[branchcode].indexOf(new_slot) < 0 )
301                     opening_slots[branchcode].push(new_slot);
302
303                 refresh_pickup_hours(branchcode);
304             })
305         });
306     </script>
307 [% END %]
308 [% INCLUDE 'intranet-bottom.inc' %]